diff --git a/.github/ISSUE_TEMPLATE/ask-question.yml b/.github/ISSUE_TEMPLATE/ask-question.yml index dce598c6..f5ad8501 100644 --- a/.github/ISSUE_TEMPLATE/ask-question.yml +++ b/.github/ISSUE_TEMPLATE/ask-question.yml @@ -1,7 +1,7 @@ name: 🙋‍♂️ Ask a question description: Tell us what's on your mind -title: "[question]: " -labels: ["question"] +title: '[question]: ' +labels: ['question'] # assignees: # - OneSignal/ios-sdk body: diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index a80fde12..2c8e9351 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,7 +1,7 @@ name: 🪳 Bug report description: File a bug report -title: "[Bug]: " -labels: ["bug", "triage"] +title: '[Bug]: ' +labels: ['bug', 'triage'] # assignees: # - OneSignal/ios-sdk body: diff --git a/.github/ISSUE_TEMPLATE/general-feedback.yml b/.github/ISSUE_TEMPLATE/general-feedback.yml index fbada335..0776fab6 100644 --- a/.github/ISSUE_TEMPLATE/general-feedback.yml +++ b/.github/ISSUE_TEMPLATE/general-feedback.yml @@ -1,7 +1,7 @@ name: 📣 General feedback description: Tell us what's on your mind -title: "[Feedback]: " -labels: ["triage"] +title: '[Feedback]: ' +labels: ['triage'] # assignees: # - OneSignal/ios-sdk body: diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 1ce9a81a..ad828eb8 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,60 +1,75 @@ + # READ AND DELETE THIS SECTION BEFORE SUBMITTING PR -* **Fill out each _REQUIRED_ section** -* **Fill out _OPTIONAL_ sections, remove section if it doesn't apply to your PR** -* **Read and fill out each of the checklists below** -* **Remove this section after reading** + +- **Fill out each _REQUIRED_ section** +- **Fill out _OPTIONAL_ sections, remove section if it doesn't apply to your PR** +- **Read and fill out each of the checklists below** +- **Remove this section after reading** # Description + ## One Line Summary + **REQUIRED** - Very short description that summaries the changes in this PR. ## Details ### Motivation + **REQUIRED -** Why is this code change being made? Or what is the goal of this PR? Examples: Fixes a specific bug, provides additional logging to debug future issues, feature to allow X. ### Scope + **RECOMMEND - OPTIONAL -** What is intended to be effected. What is known not to change. Example: Notifications are grouped when parameter X is set, not enabled by default. ### OPTIONAL - Other + **OPTIONAL -** Feel free to add any other sections or sub-sections that can explain your PR better. # Testing + ## Unit testing -**OPTIONAL -** Explain unit tests added, if not clear in the code. + +**OPTIONAL -** Explain unit tests added, if not clear in the code. ## Manual testing + **RECOMMEND - OPTIONAL -** Explain what scenarios were tested and the environment. Example: Tested opening a notification while the app was foregrounded, app build with Android Studio 2020.3 with a fresh install of the OneSignal example app on a Pixel 6 with Android 12. # Affected code checklist - - [ ] Notifications - - [ ] Display - - [ ] Open - - [ ] Push Processing - - [ ] Confirm Deliveries - - [ ] Outcomes - - [ ] Sessions - - [ ] In-App Messaging - - [ ] REST API requests - - [ ] Public API changes + +- [ ] Notifications + - [ ] Display + - [ ] Open + - [ ] Push Processing + - [ ] Confirm Deliveries +- [ ] Outcomes +- [ ] Sessions +- [ ] In-App Messaging +- [ ] REST API requests +- [ ] Public API changes # Checklist + ## Overview - - [ ] I have filled out all **REQUIRED** sections above - - [ ] PR does one thing - - If it is hard to explain how any codes changes are related to each other then it most likely needs to be more than one PR - - [ ] Any Public API changes are explained in the PR details and conform to existing APIs + +- [ ] I have filled out all **REQUIRED** sections above +- [ ] PR does one thing + - If it is hard to explain how any codes changes are related to each other then it most likely needs to be more than one PR +- [ ] Any Public API changes are explained in the PR details and conform to existing APIs ## Testing - - [ ] I have included test coverage for these changes, or explained why they are not needed - - [ ] All automated tests pass, or I explained why that is not possible - - [ ] I have personally tested this on my device, or explained why that is not possible + +- [ ] I have included test coverage for these changes, or explained why they are not needed +- [ ] All automated tests pass, or I explained why that is not possible +- [ ] I have personally tested this on my device, or explained why that is not possible ## Final pass - - [ ] Code is as readable as possible. - - Simplify with less code, followed by splitting up code into well named functions and variables, followed by adding comments to the code. - - [ ] I have reviewed this PR myself, ensuring it meets each checklist item - - WIP (Work In Progress) is ok, but explain what is still in progress and what you would like feedback on. Start the PR title with "WIP" to indicate this. \ No newline at end of file + +- [ ] Code is as readable as possible. + - Simplify with less code, followed by splitting up code into well named functions and variables, followed by adding comments to the code. +- [ ] I have reviewed this PR myself, ensuring it meets each checklist item + - WIP (Work In Progress) is ok, but explain what is still in progress and what you would like feedback on. Start the PR title with "WIP" to indicate this. diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index a7a42bde..5591cb45 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -6,9 +6,9 @@ categories: - title: 🐛 Bug Fixes label: Bug - title: 🧰 Improvements - label: Improvement + label: Improvement - title: down arrow Dependency Updates - label: Dependencies + label: Dependencies change-template: '- $TITLE (#$NUMBER)' version-resolver: major: @@ -23,5 +23,5 @@ version-resolver: default: patch template: | ## Other Changes - + $CHANGES diff --git a/.github/workflows/Zapier.yml b/.github/workflows/Zapier.yml index 3665dd58..5aab0bbf 100644 --- a/.github/workflows/Zapier.yml +++ b/.github/workflows/Zapier.yml @@ -7,7 +7,7 @@ on: # Triggers the workflow on push or pull request events but only for the "main" branch issues: types: [closed] - + permissions: issues: read diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af204294..eac8cfbf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,20 +2,20 @@ name: Test on: pull_request: - branches: "**" + branches: '**' jobs: build: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 - - name: "[Setup] Node" + - name: '[Setup] Node' uses: actions/setup-node@v3 with: node-version: 16 - - name: "[Setup] Dependencies" + - name: '[Setup] Dependencies' run: yarn - - name: "[Test] Linting" + - name: '[Test] Linting' run: yarn lint - name: Unit tests results diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..cad67cef --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,82 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "main", "major_release_5.0.0" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "main", "major_release_5.0.0" ] + schedule: + - cron: '37 19 * * 4' + +jobs: + analyze: + name: Analyze + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners + # Consider using larger runners for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'javascript-typescript' ] + # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ] + # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/npm_deploy.yml b/.github/workflows/npm_deploy.yml new file mode 100644 index 00000000..71d014cd --- /dev/null +++ b/.github/workflows/npm_deploy.yml @@ -0,0 +1,18 @@ +name: NPM Publish + +on: + release: + types: [created] + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - name: Publish package + uses: JS-DevTools/npm-publish@v1 + with: + token: ${{ secrets.NPM }} diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index a64b3721..82e66d26 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -1,4 +1,3 @@ - name: Release Drafter on: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e13790dd..282a6ee1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,6 +3,7 @@ :+1::tada: First off, thanks for taking the time to contribute! :tada::+1: ### How to Contribute + We love the open source community and enjoy the support and contributions of many of our users. We ask that any potential contributors to the SDK Follow the following guidelines: If your proposed contribution is a small bug fix, please feel free to create your own fork of the repository and create a pull request. @@ -10,13 +11,15 @@ If your proposed contribution is a small bug fix, please feel free to create you If your contribution would _break_ or _change_ the functionality of the SDK, please reach out to us on (contact) before you put in a lot of effort into a change we may not be able to use. We try our best to make sure that the SDK remains stable so that developers do not have to continually change their code, however some breaking changes _are_ desirable, so please get in touch to discuss your idea before you put in a lot of effort. #### Reporting Bugs -If you have found a bug with the SDK, please feel free to open an Issue. + +If you have found a bug with the SDK, please feel free to open an Issue. If you are pretty certain that the issue is only related to the native iOS SDK, please open the issue in our [native iOS SDK repository](https://github.com/OneSignal/OneSignal-iOS-SDK). If you are certain the issue is contained to the Android SDK, please open the issue in our [Android SDK repository](https://github.com/OneSignal/OneSignal-Android-SDK) #### Before Submitting A Bug Report + Before creating bug reports, please check this list of steps to follow. 1. Make sure that you are actually encountering an _issue_ and not a _question_. If you simply have a question about the SDK, we would be more than happy to assist you in our Support section on the web (https://www.onesignal.com - click the Message button at the bottom right) @@ -24,10 +27,10 @@ Before creating bug reports, please check this list of steps to follow. > **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. - #### How Do I Submit a Good Bug Report -* **Use a clear and descriptive title** for the issue to identify the problem. -* **Include Reproducibility** It is nearly always a good idea to include steps to reproduct the issue. If you cannot reliably reproduce the issue yourself, that's ok, but reproducible steps help best. -* **Describe your environment**, tell us what version of react-native your app is using, what version of the react-native-onesignal SDK you're using, how you added it to your project, and so on. -* **Include a Stack Trace** If your issue involves a crash/exception, ***PLEASE*** post the stack trace to help us identify the root issue. -* **Include an Example Project** This isn't required, but if you want your issue fixed quickly, it's often a good idea to include an example project as a zip and include it with the issue. You can also download the Demo project (included in the `/examples` folder of this repo) and set up an example project with this code as a starting point. + +- **Use a clear and descriptive title** for the issue to identify the problem. +- **Include Reproducibility** It is nearly always a good idea to include steps to reproduct the issue. If you cannot reliably reproduce the issue yourself, that's ok, but reproducible steps help best. +- **Describe your environment**, tell us what version of react-native your app is using, what version of the react-native-onesignal SDK you're using, how you added it to your project, and so on. +- **Include a Stack Trace** If your issue involves a crash/exception, **_PLEASE_** post the stack trace to help us identify the root issue. +- **Include an Example Project** This isn't required, but if you want your issue fixed quickly, it's often a good idea to include an example project as a zip and include it with the issue. You can also download the Demo project (included in the `/examples` folder of this repo) and set up an example project with this code as a starting point. diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md new file mode 100644 index 00000000..41136a4b --- /dev/null +++ b/MIGRATION_GUIDE.md @@ -0,0 +1,409 @@ +# React Native v5.0.0 Migration Guide + +# Intro + +In this release, we are making a significant shift from a device-centered model to a user-centered model. A user-centered model allows for more powerful omni-channel integrations within the OneSignal platform. + +To facilitate this change, the `externalId` approach for identifying users is being replaced by the `login` and `logout` methods. In addition, the SDK now makes use of namespaces such as `User`, `Notifications`, and `InAppMessages` to better separate code. + +This migration guide will walk you through the React Native SDK changes as a result of this shift. + +# Overview + +Under the user-centered model, the concept of a "player" is being replaced with three new concepts: **users**, **subscriptions**, and **aliases**. + +## Users + +A user is a new concept which is meant to represent your end-user. A user has zero or more subscriptions and can be uniquely identified by one or more aliases. In addition to subscriptions, a user can have **data tags** which allows for user attribution. + +## Subscription + +A subscription refers to the method in which an end-user can receive various communications sent by OneSignal, including push notifications, SMS, and email. In previous versions of the OneSignal platform, each of these channels was referred to as a “player”. A subscription is in fact identical to the legacy “player” concept. Each subscription has a **subscription_id** (previously, player_id) to uniquely identify that communication channel. + +## Aliases + +Aliases are a concept evolved from [external user ids](https://documentation.onesignal.com/docs/external-user-ids) which allows the unique identification of a user within a OneSignal application. Aliases are a key-value pair made up of an **alias label** (the key) and an **alias id** (the value). The **alias label** can be thought of as a consistent keyword across all users, while the **alias id** is a value specific to each user for that particular label. The combined **alias label** and **alias id** provide uniqueness to successfully identify a user. + +OneSignal uses a built-in **alias label** called `external_id` which supports existing use of [external user ids](https://documentation.onesignal.com/docs/external-user-ids). `external_id` is also used as the identification method when a user identifies themselves to the OneSignal SDK via `OneSignal.login`. Multiple aliases can be created for each user to allow for your own application's unique identifier as well as identifiers from other integrated applications. + +# Migration Guide (v4 to v5) + +The React Native SDK accesses the OneSignal native iOS and Android SDKs. For this update, all SDK versions are aligning across OneSignal’s suite of client SDKs. As such, the native iOS SDK is making the jump from `v3` to `v5`. See existing install instructions [here](https://documentation.onesignal.com/docs/react-native-sdk-setup) for more information. + +## iOS +### Notification Service Extension Changes + +In your Project Root > ios > Podfile, update the notification service extension: + +``` + // 4.x.x + target 'OneSignalNotificationServiceExtension' do + pod 'OneSignalXCFramework', '>= 3.0', '< 4.0' + end + + // 5.x.x + target 'OneSignalNotificationServiceExtension' do + pod 'OneSignalXCFramework', '>= 5.0', '< 6.0' + end +``` + +Close Xcode. While still in the ios directory, run `pod install --repo-update`. + +# API Changes + +## Namespaces + +The OneSignal SDK has been updated to be more modular in nature. The SDK has been split into namespaces, and functionality previously in the static `OneSignal` class has been moved to the appropriate namespace. The namespaces and how to access them in code are as follows: + +| **Namespace** | **Access Pattern** | +| -------------- | -------------------------- | +| Debug | `OneSignal.Debug` | +| InAppMessages | `OneSignal.InAppMessages` | +| LiveActivities | `OneSignal.LiveActivities` | +| Location | `OneSignal.Location` | +| Notifications | `OneSignal.Notifications` | +| Session | `OneSignal.Session` | +| User | `OneSignal.User` | + +## Initialization + +Initialization of the OneSignal SDK is now completed through the `initialize` method. A typical initialization now looks similar to below. + +Navigate to your index.ts file, or the first Javascript file that loads with your app. + +Replace the following: + +```typescript +OneSignal.setAppId('YOUR_ONESIGNAL_APP_ID'); +``` + +To the match the new initialization: + +```typescript +OneSignal.initialize('YOUR_ONESIGNAL_APP_ID'); +``` + +**for iOS:** Remove any usages of `setLaunchURLsInApp` as the method and functionality has been removed. + +If your integration is **not** user-centric, there is no additional startup code required. A device-scoped user _(please see definition of “**device-scoped user**” below in Glossary)_ is automatically created as part of the push subscription creation, both of which are only accessible from the current device or through the OneSignal dashboard. + +If your integration is user-centric, or you want the ability to identify the user beyond the current device, the `login` method should be called to identify the user: + +```typescript +OneSignal.login('USER_EXTERNAL_ID'); +``` + +The `login` method will associate the device’s push subscription to the user that can be identified via the alias `externalId=USER_EXTERNAL_ID`. If that user doesn’t already exist, it will be created. If the user does already exist, the user will be updated to own the device’s push subscription. Note that the push subscription for the device will always be transferred to the newly logged in user, as that user is the current owner of that push subscription. + +Once (or if) the user is no longer identifiable in your app (i.e. they logged out), the `logout` method should be called: + +```typescript +OneSignal.logout(); +``` + +Logging out has the affect of reverting to a device-scoped user, which is the new owner of the device’s push subscription. + +## Subscriptions + +In previous versions of the SDK, a “player” could have up to one email address and up to one phone number for SMS. In the user-centered model, a user can own the current device’s **Push Subscription** along with the ability to have **zero or more** email subscriptions and **zero or more** SMS subscriptions. Note: If a new user logs in via the `login` method, the previous user will no longer own that push subscription. + +### **Push Subscription** + +The current device’s push subscription can be retrieved via: + +```typescript +const id: string = OneSignal.User.pushSubscription.getPushSubscriptionId(); +const token: string = OneSignal.User.pushSubscription.getPushSubscriptionToken(); +const optedIn: boolean = OneSignal.User.pushSubscription.getOptedIn(); +``` + +### **Opting In and Out of Push Notifications** + +To receive push notifications on the device, call the push subscription’s `optIn()` method. If needed, this method will prompt the user for push notifications permission. + +Note: For greater control over prompting for push notification permission, you may use the `OneSignal.Notifications.requestPermission` method detailed below in the API Reference. + +```typescript +OneSignal.User.pushSubscription.optIn(); +``` + +If at any point you want the user to stop receiving push notifications on the current device (regardless of system-level permission status), you can use the push subscription to opt out: + +```typescript +OneSignal.User.pushSubscription.optOut(); +``` + +To resume receiving of push notifications (driving the native permission prompt if permissions are not available), you can opt back in with the `optIn` method from above. + +### **Email/SMS Subscriptions** + +Email and/or SMS subscriptions can be added or removed via the following methods. The remove methods will result in a no-op if the specified email or SMS number does not exist on the user within the SDK, and no request will be made. + +```typescript +// Add email subscription +OneSignal.User.addEmail('customer@company.com'); +// Remove previously added email subscription +OneSignal.User.removeEmail('customer@company.com'); + +// Add SMS subscription +OneSignal.User.addSms('+15558675309'); +// Remove previously added SMS subscription +OneSignal.User.removeSms('+15558675309'); +``` + +# API Reference + +Below is a comprehensive reference to the `5.0.0` OneSignal React Native SDK. + +## OneSignal + +The SDK is still accessible via a `OneSignal` static class. It provides access to higher level functionality and is a gateway to each subspace of the SDK. + +| **React Native** | **Description** | +| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `OneSignal.initialize("YOUR_ONESIGNAL_APP_ID")` | _Initializes the OneSignal SDK. This should be called during startup of the application._ | +| `OneSignal.login("USER_EXTERNAL_ID")` | _Login to OneSignal under the user identified by the [externalId] provided. The act of logging a user into the OneSignal SDK will switch the [user] context to that specific user.

- If the [externalId] exists, the user will be retrieved and the context will be set from that user information. If operations have already been performed under a device-scoped user, they **_will not_** be applied to the now logged in user (they will be lost).
- If the [externalId] does not exist the user, the user will be created and the context set from the current local state. If operations have already been performed under a device-scoped user, those operations **_will_** be applied to the newly created user.

**_Push Notifications and In App Messaging_**
Logging in a new user will automatically transfer the push notification and in app messaging subscription from the current user (if there is one) to the newly logged in user. This is because both push notifications and in-app messages are owned by the device._ | +| `OneSignal.logout()` | _Logout the user previously logged in via [login]. The [user] property now references a new device-scoped user. A device-scoped user has no user identity that can later be retrieved, except through this device as long as the app remains installed and the app data is not cleared._ | +| `OneSignal.setConsentGiven(true)` | _Indicates whether privacy consent has been granted. This field is only relevant when the application has opted into data privacy protections. See [requiresPrivacyConsent]._ | +| `OneSignal.setConsentRequired(true)` | _Determines whether a user must consent to privacy prior to their user data being sent up to OneSignal. This should be set to `true` prior to the invocation of `initialize` to ensure compliance._ + +## Live Activities Namespace + +Live Activities are a type of interactive push notification. Apple introduced them in October 2022 to enable iOS apps to provide real-time updates to their users that are visible from the lock screen and the dynamic island. + +Please refer to OneSignal’s guide on [Live Activities](https://documentation.onesignal.com/docs/live-activities), the [Live Activities Quickstart](https://documentation.onesignal.com/docs/live-activities-quickstart) tutorial, and the [existing SDK reference](https://documentation.onesignal.com/docs/live-activities-sdk-methods) on Live Activities. + +| **React Native** | **Description** | +| ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `OneSignal.LiveActivities.enter("ACTIVITY_ID", "TOKEN")`

**_See below for usage of callbacks_** | _Entering a Live Activity associates an `activityId` with a live activity temporary push `token` on OneSignal's server. The activityId is then used with the OneSignal REST API to update one or multiple Live Activities at one time._ | +| `OneSignal.LiveActivities.exit("ACTIVITY_ID")`

**_See below for usage of callbacks_** | _Exiting a Live activity deletes the association between a customer defined `activityId` with a Live Activity temporary push `token` on OneSignal's server._ | + +```typescript +// Enter a Live Activity +OneSignal.LiveActivities.enter('ACTIVITY_ID', 'TOKEN', (results) => { + console.log('Results of entering live activity'); + console.log(results); +}); + +// Exit a Live Activity +OneSignal.LiveActivities.exit('ACTIVITY_ID', (results) => { + console.log('Results of exiting live activity'); + console.log(results); +}); +``` + +## User Namespace + +The User namespace is accessible via `OneSignal.User` and provides access to user-scoped functionality. + +| **React Native** | **Description** | +| ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `OneSignal.User.setLanguage("en")` | _Set the 2-character language for this user._ | +| `OneSignal.User.addAlias("ALIAS_LABEL", "ALIAS_ID")` | _Set an alias for the current user. If this alias label already exists on this user, it will be overwritten with the new alias id._ | +| `OneSignal.User.addAliases({ALIAS_LABEL_01: "ALIAS_ID_01", ALIAS_LABEL_02: "ALIAS_ID_02"})` | _Set aliases for the current user. If any alias already exists, it will be overwritten to the new values._ | +| `OneSignal.User.removeAlias("ALIAS_LABEL")` | _Remove an alias from the current user._ | +| `OneSignal.User.removeAliases(["ALIAS_LABEL_01", "ALIAS_LABEL_02"]])` | _Remove aliases from the current user._ | +| `OneSignal.User.addEmail("customer@company.com")` | _Add a new email subscription to the current user._ | +| `OneSignal.User.removeEmail("customer@company.com")` | _Results in a no-op if the specified email does not exist on the user within the SDK, and no request will be made._ | +| `OneSignal.User.addSms("+15558675309")` | _Add a new SMS subscription to the current user._ | +| `OneSignal.User.removeSms("+15558675309")` | _Results in a no-op if the specified phone number does not exist on the user within the SDK, and no request will be made.._ | +| `OneSignal.User.addTag("KEY", "VALUE")` | _Add a tag for the current user. Tags are key:value pairs used as building blocks for targeting specific users and/or personalizing messages. If the tag key already exists, it will be replaced with the value provided here._ | +| `OneSignal.User.addTags({"KEY_01": "VALUE_01", "KEY_02": "VALUE_02"})` | _Add multiple tags for the current user. Tags are key:value pairs used as building blocks for targeting specific users and/or personalizing messages. If the tag key already exists, it will be replaced with the value provided here._ | +| `OneSignal.User.removeTag("KEY")` | _Remove the data tag with the provided key from the current user._ | +| `OneSignal.User.removeTags(["KEY_01", "KEY_02"])` | _Remove multiple tags with the provided keys from the current user._ | +| `OneSignal.User.getTags()` | _Returns the local tags for the current user._| +| `OneSignal.User.addEventListener("change", (event: UserChangedState) => void)`

**_See below for usage_** | _Add a User State callback which contains the nullable onesignalId and externalId. The listener will be fired when these values change._| +| `await OneSignal.User.getOnesignalId()` | _Returns the OneSignal ID for the current user, which can be null if it is not yet available._| +| `await OneSignal.User.getExternalId()` | _Returns the External ID for the current user, which can be null if not set._| + +### User State Listener + +```typescript + const listener = (event: UserChangedState) => { + console.log("User changed: " + (event)); + }; + + OneSignal.User.addEventListener("change", listener); + // Remove the listener + OneSignal.User.removeEventListener("change", listener); +``` + +## Push Subscription Namespace + +The Push Subscription namespace is accessible via `OneSignal.User.pushSubscription` and provides access to push subscription-scoped functionality. + +| **React Native** | **Description** | +| --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `OneSignal.User.pushSubscription.getPushSubscriptionId()` | _**DEPRECATED**
use `getIdAsync`._ | +| `OneSignal.User.pushSubscription.getPushSubscriptionToken()` | _**DEPRECATED**
use `getTokenAsync`_ | +| `OneSignal.User.pushSubscription.getOptedIn()` | _**DEPRECATED**
use `getOptedInAsync`_ | +| `await OneSignal.User.pushSubscription.getIdAsync()` | _The readonly push subscription ID._ | +| `await OneSignal.User.pushSubscription.getTokenAsync()` | _The readonly push token._ | +| `await OneSignal.User.pushSubscription.getOptedInAsync()` | _Gets a boolean value indicating whether the current user is opted in to push notifications. This returns `true` when the app has notifications permission and `optedOut` is called. **_Note:_** Does not take into account the existence of the subscription ID and push token. This boolean may return `true` but push notifications may still not be received by the user._ | +| `OneSignal.User.pushSubscription.optIn()` | _Call this method to receive push notifications on the device or to resume receiving of push notifications after calling `optOut`. If needed, this method will prompt the user for push notifications permission._ | +| `OneSignal.User.pushSubscription.optOut()` | _If at any point you want the user to stop receiving push notifications on the current device (regardless of system-level permission status), you can call this method to opt out._ | +| `OneSignal.User.pushSubscription.addEventListener('change', listener: (event) => void)`

**_See below for usage_** | _Adds the listener to run when the push subscription changes._ | +| `OneSignal.User.pushSubscription.removeEventListener('change', listener)`

**_See below for usage_** | _Remove a push subscription listener that has been previously added._ | + +### Push Subscription Observer + +```typescript +// Create an observer +OneSignal.User.pushSubscription.addEventListener('change', (subscription) => { + console.log('OneSignal: subscription changed:', subscription); +}); + +// Removes the previously added observer +OneSignal.User.pushSubscription.removeEventListener('change', subscription); +``` + +## Session Namespace + +The Session namespace is accessible via `OneSignal.Session` and provides access to session-scoped functionality. + +| **React Native** | **Description** | +| ---------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| `OneSignal.Session.addOutcome("OUTCOME_NAME")` | _Add an outcome with the provided name, captured against the current session._ | +| `OneSignal.Session.addUniqueOutcome("OUTCOME_NAME")` | _Add a unique outcome with the provided name, captured against the current session._ | +| `OneSignal.Session.addOutcomeWithValue("OUTCOME_NAME", 1)` | _Add an outcome with the provided name and value, captured against the current session._ | + +## Notifications Namespace + +The Notifications namespace is accessible via `OneSignal.Notifications` and provides access to notification-scoped functionality. + +| **React Native** | **Description** | +|--------------------------------------- | --------------- | +| `OneSignal.Notifications.hasPermission()` | _**DEPRECATED**
use `getPermissionAsync()`_ | +| `OneSignal.Notifications.getPermissionAsync()` | _Whether this app has push notification permission._ | +| `await OneSignal.Notifications.canRequestPermission()` | _Whether attempting to request notification permission will show a prompt. Returns `true` if the device has not been prompted for push notification permission already._ | +| `await OneSignal.Notifications.permissionNative()` | _(ios only) Returns the enum for the native permission of the device. It will be one of: NotDetermined, Denied, Authorized, Provisional (only available in iOS 12), Ephemeral (only available in iOS 14)_ | +| `OneSignal.Notifications.clearAll();` | _Removes all OneSignal notifications._ | +| `OneSignal.Notifications.removeNotification(32432)` | _(Android only) Cancels a single OneSignal notification based on its Android notification integer ID. Use instead of Android's [android.app.NotificationManager.cancel], otherwise the notification will be restored when your app is restarted._ | +| `OneSignal.Notifications.removeGroupedNotifications("GROUP_KEY")` | _(Android only) Cancels a group of OneSignal notifications with the provided group key. Grouping notifications is a OneSignal concept, there is no [android.app.NotificationManager] equivalent._ | +| `await OneSignal.Notifications.requestPermission(fallbackToSettings: boolean)`

**_See below for usage_** | _Prompt the user for permission to receive push notifications. This will display the native system prompt to request push notification permission._ | +| `OneSignal.Notifications.registerForProvisionalAuthorization()` | _(iOS only) Instead of having to prompt the user for permission to send them push notifications, your app can request provisional authorization._ | +| `OneSignal.Notifications.addEventListener("permissionChange", (observer) => {});`

**_See below for usage_** | _This method will fire when a notification permission setting changes. This happens when the user enables or disables notifications for your app from the system settings outside of your app._ | +| `OneSignal.Notifications.removeEventListener("permissionChange", (observer) => {});`

**_See below for usage_** | _Remove a push permission observer that has been previously added._ | +| `OneSignal.Notifications.addEventListener("foregroundWillDisplay", (event) => {};)`

**_See below for usage_** | _Sets the handler to run before displaying a notification while the app is in focus. Use this handler to read notification data and change it or decide if the notification **_should_** show or not.

**_Note:_** this runs **_after_** the [Notification Service Extension](https://documentation.onesignal.com/docs/service-extensions) which can be used to modify the notification before showing it._ | +| `OneSignal.Notifications.addEventListener("click", (event) => {};)`

**_See below for usage_** | _Sets a handler that will run whenever a notification is opened by the user._ | + +### Prompt for Push Notification Permission + +```typescript +OneSignal.Notifications.requestPermission(true).then(accepted => { + console.log('User accepted notifications: ' + accepted); +}); +``` + +### Permission Observer + +Add an observer when permission status changes. You can call `removeEventListener` to remove any existing listeners. + +```typescript +// Add an observer +OneSignal.Notifications.addEventListener('permissionChange', (granted: boolean) => { + console.log('OneSignal: permission changed:', granted); +}); + +// Remove previously added observer +OneSignal.Notifications.removeEventListener('permissionChange', observer); +``` + +### Notification Lifecycle Listener + +```typescript +OneSignal.Notifications.addEventListener('foregroundWillDisplay', (event: NotificationWillDisplayEvent) => { + event.preventDefault(); + // some async work + + // Use display() to display the notification after some async work + event.getNotification().display(); +}); +``` + +### Notification Click Listener + +```typescript +OneSignal.Notifications.addEventListener('click', (event: NotificationClickEvent) => { + console.log('OneSignal: notification clicked: ' + event); +}); +``` + +## Location Namespace + +The Location namespace is accessible via `OneSignal.Location` and provide access to location-scoped functionality. + +| **React Native** | **Description** | +| ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `OneSignal.Location.setShared(shared: boolean)` | _Set whether location is currently shared with OneSignal._ | +| `await OneSignal.Location.isShared()` | _Whether location is currently shared with OneSignal._ | +| `OneSignal.Location.requestPermission()` | _Use this method to manually prompt the user for location permissions. This allows for geotagging so you send notifications to users based on location._ | + +## InAppMessages Namespace + +The In App Messages namespace is accessible via `OneSignal.InAppMessages` and provide access to in app messages-scoped functionality. + +| **React Native** | **Description** | +| ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `await OneSignal.InAppMessages.getPaused()`

`OneSignal.InAppMessages.setPaused(true)` | _Whether in-app messaging is currently paused. When set to `true`, no IAM will be presented to the user regardless of whether they qualify for them. When set to `false`, any IAMs the user qualifies for will be presented to the user at the appropriate time._ | +| `OneSignal.InAppMessages.addTrigger("triggerKey", "triggerValue")` | _Add a trigger for the current user. Triggers are currently explicitly used to determine whether a specific IAM should be displayed to the user. See [Triggers](https://documentation.onesignal.com/docs/iam-triggers).

If the trigger key already exists, it will be replaced with the value provided here. Note that triggers are not persisted to the backend. They only exist on the local device and are applicable to the current user._ | +| `OneSignal.InAppMessages.addTriggers({"triggerKey1":"triggerValue", "triggerKey2": "triggerValue"})` | _Add multiple triggers for the current user. Triggers are currently explicitly used to determine whether a specific IAM should be displayed to the user. See [Triggers](https://documentation.onesignal.com/docs/iam-triggers).

If any trigger key already exists, it will be replaced with the value provided here. Note that triggers are not persisted to the backend. They only exist on the local device and are applicable to the current user._ | +| `OneSignal.InAppMessages.removeTrigger("triggerKey")` | _Remove the trigger with the provided key from the current user._ | +| `OneSignal.InAppMessages.removeTriggers(["triggerKey1", "triggerKey2"])` | _Remove multiple triggers from the current user._ | +| `OneSignal.InAppMessages.clearTriggers()` | _Clear all triggers from the current user._ | +| ` OneSignal.InAppMessages.setLifecycleHandler(handlerObject)`

**_See below for usage_** | _Set the in-app message lifecycle handler._ | +| `OneSignal.InAppMessages.setClickHandler(handler)`

**_See below for usage_** | _Set the in-app message click handler._ | + +### In-App Message Click Listener + +```typescript +OneSignal.InAppMessages.addEventListener('click', (event) => { + console.log('OneSignal IAM clicked: ' + event); +}); +``` + +### In-App Message Lifecycle Listeners + +```typescript +OneSignal.InAppMessages.addEventListener('willDisplay', (event) => { + console.log('OneSignal: will display IAM: ', event); +}); + +OneSignal.InAppMessages.addEventListener('didDisplay', (event) => { + console.log('OneSignal: did display IAM: ', event); +}); + +OneSignal.InAppMessages.addEventListener('willDismiss', (event) => { + console.log('OneSignal: will dismiss IAM: ', event); +}); + +OneSignal.InAppMessages.addEventListener('didDismiss', (event) => { + console.log('OneSignal: did dismiss IAM: ', event); +}); +``` + +## Debug Namespace + +The Debug namespace is accessible via `OneSignal.Debug` and provide access to debug-scoped functionality. + +| **React Native** | **Description** | +| ---------------------------------- | -------------------------------------------------------------------------- | +| `OneSignal.Debug.setLogLevel(LogLevel.Verbose)` | _Sets the log level the OneSignal SDK should be writing to the Xcode log._ | +| `OneSignal.Debug.setAlertLevel(LogLevel.Verbose)` | _Sets the logging level to show as alert dialogs._ | + +# Glossary + +**device-scoped user** + +> An anonymous user with no aliases that cannot be retrieved except through the current device or OneSignal dashboard. On app install, the OneSignal SDK is initialized with a _device-scoped user_. A _device-scoped user_ can be upgraded to an identified user by calling `OneSignal.login("USER_EXTERNAL_ID")` to identify the user by the specified external user ID. + +# Limitations + +- Changing app IDs is not supported. +- Any `User` namespace calls must be invoked **after** initialization. Example: `OneSignal.User.addTag("tag", "2")` +- In the SDK, the user state is only refreshed from the server when a new session is started (cold start or backgrounded for over 30 seconds) or when the user is logged in. This is by design. + +# Known issues + +- Identity Verification + - We will be introducing Identity Verification using JWT in a follow up release diff --git a/README.md b/README.md index eac166ec..8afe8682 100755 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@

### React Native OneSignal SDK + [![npm version](https://img.shields.io/npm/v/react-native-onesignal.svg)](https://www.npmjs.com/package/react-native-onesignal) [![npm downloads](https://img.shields.io/npm/dm/react-native-onesignal.svg)](https://www.npmjs.com/package/react-native-onesignal) --- @@ -10,18 +11,18 @@ [OneSignal](https://onesignal.com/) is a free email, sms, push notification, and in-app message service for mobile apps. This SDK makes it easy to integrate your native React-Native iOS and/or Android apps with OneSignal. #### Installation + See the [Setup Guide](https://documentation.onesignal.com/docs/react-native-sdk-setup) for setup instructions. #### Change Log + See this repository's [release tags](https://github.com/OneSignal/react-native-onesignal/releases) for a complete change log of every released version. #### Support + Please visit this repository's [Github issue tracker](https://github.com/OneSignal/react-native-onesignal/issues) for feature requests and bug reports related specifically to the SDK. For account issues and support please contact OneSignal support from the [OneSignal.com](https://onesignal.com) dashboard. #### Demo Project -To make things easier, we have published demo projects in the `/examples` folder of this repository. -#### Supports: -* Tested from iOS 7 to iOS 13 -* Tested from Android 4.0.3 (API level 15) to Android 9 (28) +To make things easier, we have published demo projects in the `/examples` folder of this repository. diff --git a/android/build.gradle b/android/build.gradle index 0f67a28a..5f78813d 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -26,21 +26,12 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4" // api is used instead of implementation so the parent :app project can access any of the OneSignal Java // classes if needed. Such as com.onesignal.NotificationExtenderService - api 'com.onesignal:OneSignal:4.8.6' - + api 'com.onesignal:OneSignal:5.1.6' + testImplementation 'junit:junit:4.12' -} - -// Add the following to the top (Line 1) of your app/build.gradle if you run into any issues with duplicate classes. -// Such as the following error -// Error: more than one library with package name 'com.google.android.gms.license' - -/* -plugins { - id 'com.onesignal.androidsdk.onesignal-gradle-plugin' version '0.8.1' -} -apply plugin: 'com.onesignal.androidsdk.onesignal-gradle-plugin' -*/ +} \ No newline at end of file diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 04e285f3..dbdc05d2 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,3 @@ -#Mon Dec 28 10:00:20 PST 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/android/gradlew b/android/gradlew old mode 100644 new mode 100755 diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 473b6666..99d753b3 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,3 +1,3 @@ + package="com.onesignal.rnonesignalandroid"> diff --git a/android/src/main/java/com/geektime/rnonesignalandroid/RNOneSignal.java b/android/src/main/java/com/geektime/rnonesignalandroid/RNOneSignal.java deleted file mode 100644 index 68d4e3ed..00000000 --- a/android/src/main/java/com/geektime/rnonesignalandroid/RNOneSignal.java +++ /dev/null @@ -1,869 +0,0 @@ -/* -Modified MIT License - -Copyright 2020 OneSignal - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -1. The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -2. All copies of substantial portions of the Software may only be used in connection -with services provided by OneSignal. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -Authors: - - Avishay Bar (creator) - 1/31/16 - - Brad Hesse - - Josh Kasten - - Rodrigo Gomez-Palacio - - Michael DiCioccio -*/ - -package com.geektime.rnonesignalandroid; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; -import android.util.Log; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.LifecycleEventListener; -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.modules.core.DeviceEventManagerModule; -import com.onesignal.OSDeviceState; -import com.onesignal.OSEmailSubscriptionObserver; -import com.onesignal.OSEmailSubscriptionStateChanges; -import com.onesignal.OSInAppMessageAction; -import com.onesignal.OSNotification; -import com.onesignal.OSNotificationOpenedResult; -import com.onesignal.OSNotificationReceivedEvent; -import com.onesignal.OSOutcomeEvent; -import com.onesignal.OSPermissionObserver; -import com.onesignal.OSPermissionStateChanges; -import com.onesignal.OSSMSSubscriptionObserver; -import com.onesignal.OSSMSSubscriptionStateChanges; -import com.onesignal.OSSubscriptionObserver; -import com.onesignal.OSSubscriptionStateChanges; -import com.onesignal.OneSignal; -import com.onesignal.OneSignal.EmailUpdateError; -import com.onesignal.OneSignal.EmailUpdateHandler; -import com.onesignal.OneSignal.OSInAppMessageClickHandler; -import com.onesignal.OSInAppMessageLifecycleHandler; -import com.onesignal.OSInAppMessage; -import com.onesignal.OneSignal.OSNotificationOpenedHandler; -import com.onesignal.OneSignal.OutcomeCallback; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.HashMap; - -public class RNOneSignal extends ReactContextBaseJavaModule - implements - OSPermissionObserver, - OSSubscriptionObserver, - OSNotificationOpenedHandler, - OSEmailSubscriptionObserver, - LifecycleEventListener, - OSInAppMessageClickHandler, - OSSMSSubscriptionObserver { - - public static final String HIDDEN_MESSAGE_KEY = "hidden"; - - private ReactApplicationContext mReactApplicationContext; - private ReactContext mReactContext; - - private boolean oneSignalInitDone; - - private OSInAppMessageAction inAppMessageActionResult; - - private HashMap notificationReceivedEventCache; - - private boolean hasSetInAppClickedHandler = false; - private boolean hasSetSubscriptionObserver = false; - private boolean hasSetEmailSubscriptionObserver = false; - private boolean hasSetSMSSubscriptionObserver = false; - private boolean hasSetPermissionObserver = false; - - // A native module is supposed to invoke its callback only once. It can, however, store the callback and invoke it later. - // It is very important to highlight that the callback is not invoked immediately after the native function completes - // - remember that bridge communication is asynchronous, and this too is tied to the run loop. - // Once you have done invoke() on the callback, you cannot use it again. Store it here. - private Callback pendingGetTagsCallback; - - private String appIdFromManifest(ReactApplicationContext context) { - try { - ApplicationInfo ai = context.getPackageManager().getApplicationInfo(context.getPackageName(), context.getPackageManager().GET_META_DATA); - Bundle bundle = ai.metaData; - return bundle.getString("onesignal_app_id"); - } catch (Throwable t) { - t.printStackTrace(); - return null; - } - } - - private void removeObservers() { - this.removeEmailSubscriptionObserver(); - this.removePermissionObserver(); - this.removeSubscriptionObserver(); - this.removeSMSSubscriptionObserver(); - } - - private void removeHandlers() { - OneSignal.setInAppMessageClickHandler(null); - OneSignal.setNotificationOpenedHandler(null); - OneSignal.setNotificationWillShowInForegroundHandler(null); - OneSignal.setInAppMessageLifecycleHandler(null); - } - - private void sendEvent(String eventName, Object params) { - mReactContext - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) - .emit(eventName, params); - } - - private JSONObject jsonFromErrorMessageString(String errorMessage) throws JSONException { - return new JSONObject().put("error", errorMessage); - } - - public RNOneSignal(ReactApplicationContext reactContext) { - super(reactContext); - mReactApplicationContext = reactContext; - mReactContext = reactContext; - mReactContext.addLifecycleEventListener(this); - notificationReceivedEventCache = new HashMap(); - } - - // Initialize OneSignal only once when an Activity is available. - // React creates an instance of this class to late for OneSignal to get the current Activity - // based on registerActivityLifecycleCallbacks it uses to listen for the first Activity. - // However it seems it is also to soon to call getCurrentActivity() from the reactContext as well. - // This will normally succeed when onHostResume fires instead. - private void initOneSignal() { - OneSignal.sdkType = "react"; - Context context = mReactApplicationContext.getCurrentActivity(); - - if (oneSignalInitDone) { - Log.e("OneSignal", "Already initialized the OneSignal React-Native SDK"); - return; - } - - oneSignalInitDone = true; - - - if (context == null) { - // in some cases, especially when react-native-navigation is installed, - // the activity can be null, so we can initialize with the context instead - context = mReactApplicationContext.getApplicationContext(); - } - - OneSignal.setInAppMessageClickHandler(this); - OneSignal.initWithContext(context); - } - - @ReactMethod - public void setAppId(String appId) { - OneSignal.setAppId(appId); - } - - /* Observers */ - @Override - public void onOSPermissionChanged(OSPermissionStateChanges stateChanges) { - Log.i("OneSignal", "sending permission change event"); - sendEvent("OneSignal-permissionChanged", RNUtils.jsonToWritableMap(stateChanges.toJSONObject())); - } - - @Override - public void onOSSubscriptionChanged(OSSubscriptionStateChanges stateChanges) { - Log.i("OneSignal", "sending subscription change event"); - sendEvent("OneSignal-subscriptionChanged", RNUtils.jsonToWritableMap(stateChanges.toJSONObject())); - } - - @Override - public void onOSEmailSubscriptionChanged(OSEmailSubscriptionStateChanges stateChanges) { - Log.i("OneSignal", "sending email subscription change event"); - sendEvent("OneSignal-emailSubscriptionChanged", RNUtils.jsonToWritableMap(stateChanges.toJSONObject())); - } - - @Override - public void onSMSSubscriptionChanged(OSSMSSubscriptionStateChanges stateChanges) { - Log.i("OneSignal", "sending SMS subscription change event"); - sendEvent("OneSignal-smsSubscriptionChanged", RNUtils.jsonToWritableMap(stateChanges.toJSONObject())); - } - - @ReactMethod - public void addPermissionObserver() { - if (!hasSetPermissionObserver) { - OneSignal.addPermissionObserver(this); - hasSetPermissionObserver = true; - } - } - - @ReactMethod - public void removePermissionObserver() { - if (hasSetPermissionObserver) { - OneSignal.removePermissionObserver(this); - hasSetPermissionObserver = false; - } - } - - @ReactMethod - public void addSubscriptionObserver() { - if (!hasSetSubscriptionObserver) { - OneSignal.addSubscriptionObserver(this); - hasSetSubscriptionObserver = true; - } - } - - @ReactMethod - public void removeSubscriptionObserver() { - if (hasSetSubscriptionObserver) { - OneSignal.removeSubscriptionObserver(this); - hasSetSubscriptionObserver = false; - } - } - - @ReactMethod - public void addEmailSubscriptionObserver() { - if (!hasSetEmailSubscriptionObserver) { - OneSignal.addEmailSubscriptionObserver(this); - hasSetEmailSubscriptionObserver = true; - } - } - - @ReactMethod - public void removeEmailSubscriptionObserver() { - if (hasSetEmailSubscriptionObserver) { - OneSignal.removeEmailSubscriptionObserver(this); - hasSetEmailSubscriptionObserver = false; - } - } - - @ReactMethod - public void addSMSSubscriptionObserver() { - if (!hasSetSMSSubscriptionObserver) { - OneSignal.addSMSSubscriptionObserver(this); - hasSetSMSSubscriptionObserver = true; - } - } - - @ReactMethod - public void removeSMSSubscriptionObserver() { - if (hasSetSMSSubscriptionObserver) { - OneSignal.removeSMSSubscriptionObserver(this); - hasSetSMSSubscriptionObserver = false; - } - } - - /* Other methods */ - - @ReactMethod - public void getDeviceState(Promise promise) { - OSDeviceState state = OneSignal.getDeviceState(); - if (state == null) { - Log.e("OneSignal", "getDeviceState: OSDeviceState is null"); - promise.reject("Null OSDeviceState", "OSDeviceState is null"); - return; - } - promise.resolve(RNUtils.jsonToWritableMap(state.toJSONObject())); - } - - @ReactMethod - public void setLanguage(String language, final Callback successCallback, final Callback failureCallback) { - OneSignal.setLanguage(language, new OneSignal.OSSetLanguageCompletionHandler() { - final Callback[] callbackArr = new Callback[]{ successCallback, failureCallback }; - @Override - public void onSuccess(String results) { - if (callbackArr[0] != null) { - if (results == null) { - results = "{'success' : 'true', 'message' : 'Successfully set language.'}"; - } - callbackArr[0].invoke(results); - callbackArr[0] = null; - callbackArr[1] = null; // prevent other callback from being invoked by another channel - } - } - - @Override - public void onFailure(OneSignal.OSLanguageError error) { - try { - if (callbackArr[1] != null) { - String errorMessage = error.getMessage(); - if (errorMessage == null) { - errorMessage = "Failed to set language."; - } - callbackArr[1].invoke(RNUtils.jsonToWritableMap(jsonFromErrorMessageString(errorMessage))); - callbackArr[0] = null; - callbackArr[1] = null; - } - } catch (JSONException exception) { - exception.printStackTrace(); - } - } - }); - } - - @ReactMethod - public void disablePush(boolean disable) { - OneSignal.disablePush(disable); - } - - @ReactMethod - public void unsubscribeWhenNotificationsAreDisabled(boolean unsubscribe) { - OneSignal.unsubscribeWhenNotificationsAreDisabled(unsubscribe); - } - - @ReactMethod - public void sendTag(String key, String value) { - OneSignal.sendTag(key, value); - } - - @ReactMethod - public void sendTags(ReadableMap tags) { - OneSignal.sendTags(RNUtils.readableMapToJson(tags)); - } - - @ReactMethod - public void deleteTags(ReadableArray tagKeys) { - OneSignal.deleteTags(RNUtils.convertReableArrayIntoStringCollection(tagKeys)); - } - - @ReactMethod - public void getTags(final Callback callback) { - if (pendingGetTagsCallback == null) - pendingGetTagsCallback = callback; - - OneSignal.getTags(new OneSignal.OSGetTagsHandler() { - @Override - public void tagsAvailable(JSONObject tags) { - if (pendingGetTagsCallback != null) - pendingGetTagsCallback.invoke(RNUtils.jsonToWritableMap(tags)); - - pendingGetTagsCallback = null; - } - }); - } - - @ReactMethod - public void setEmail(String email, String emailAuthToken, final Callback callback) { - final Callback[] callbackArr = new Callback[]{ callback }; - OneSignal.setEmail(email, emailAuthToken, new EmailUpdateHandler() { - @Override - public void onSuccess() { - if (callbackArr[0] != null) { - callbackArr[0].invoke(); - callbackArr[0] = null; - } - } - - @Override - public void onFailure(EmailUpdateError error) { - try { - if (callbackArr[0] != null) { - callbackArr[0].invoke(RNUtils.jsonToWritableMap(jsonFromErrorMessageString(error.getMessage()))); - callbackArr[0] = null; - } - } catch (JSONException exception) { - exception.printStackTrace(); - } - } - }); - } - - @ReactMethod - public void logoutEmail(final Callback callback) { - final Callback[] callbackArr = new Callback[]{ callback }; - OneSignal.logoutEmail(new EmailUpdateHandler() { - @Override - public void onSuccess() { - if (callbackArr[0] != null) { - callbackArr[0].invoke(); - callbackArr[0] = null; - } - } - - @Override - public void onFailure(EmailUpdateError error) { - try { - if (callbackArr[0] != null) { - callbackArr[0].invoke(RNUtils.jsonToWritableMap(jsonFromErrorMessageString(error.getMessage()))); - callbackArr[0] = null; - } - } catch (JSONException exception) { - exception.printStackTrace(); - } - } - }); - } - - @ReactMethod - public void setSMSNumber(String smsNumber, String smsAuthToken, final Callback callback) { - final Callback[] callbackArr = new Callback[]{ callback }; - OneSignal.setSMSNumber(smsNumber, smsAuthToken, new OneSignal.OSSMSUpdateHandler() { - @Override - public void onSuccess(JSONObject result) { - if (callbackArr[0] != null) { - callbackArr[0].invoke(RNUtils.jsonToWritableMap(result)); - callbackArr[0] = null; - } - } - - @Override - public void onFailure(OneSignal.OSSMSUpdateError error) { - try { - if (callbackArr[0] != null) { - callbackArr[0].invoke(RNUtils.jsonToWritableMap(jsonFromErrorMessageString(error.getMessage()))); - callbackArr[0] = null; - } - } catch (JSONException exception) { - exception.printStackTrace(); - } - } - }); - } - - @ReactMethod - public void logoutSMSNumber(final Callback callback) { - final Callback[] callbackArr = new Callback[]{ callback }; - OneSignal.logoutSMSNumber(new OneSignal.OSSMSUpdateHandler() { - @Override - public void onSuccess(JSONObject result) { - if (callbackArr[0] != null) { - callbackArr[0].invoke(RNUtils.jsonToWritableMap(result)); - callbackArr[0] = null; - } - } - - @Override - public void onFailure(OneSignal.OSSMSUpdateError error) { - try { - if (callbackArr[0] != null) { - callbackArr[0].invoke(RNUtils.jsonToWritableMap(jsonFromErrorMessageString(error.getMessage()))); - callbackArr[0] = null; - } - } catch (JSONException exception) { - exception.printStackTrace(); - } - } - }); - } - - @ReactMethod - public void promptForPushNotificationsWithUserResponse(final boolean fallbackToSettings, final Callback callback) { - final Callback[] callbackArr = new Callback[]{ callback }; - OneSignal.promptForPushNotifications(fallbackToSettings, new OneSignal.PromptForPushNotificationPermissionResponseHandler() { - @Override - public void response(boolean accepted) { - if (callbackArr[0] != null) { - callbackArr[0].invoke(accepted); - callbackArr[0] = null; - } - } - }); - } - - @ReactMethod - public void promptLocation() { - OneSignal.promptLocation(); - } - - @ReactMethod - public void setLogLevel(int logLevel, int visualLogLevel) { - OneSignal.setLogLevel(logLevel, visualLogLevel); - } - - @ReactMethod - public void isLocationShared(Promise promise) { - promise.resolve(OneSignal.isLocationShared()); - } - - @ReactMethod - public void setLocationShared(Boolean shared) { - OneSignal.setLocationShared(shared); - } - - @ReactMethod - public void postNotification(String jsonObjectString, final Callback successCallback, final Callback failureCallback) { - final Callback[] callbackArr = new Callback[]{ successCallback, failureCallback }; - OneSignal.postNotification( - jsonObjectString, - new OneSignal.PostNotificationResponseHandler() { - @Override - public void onSuccess(JSONObject response) { - Log.i("OneSignal", "postNotification Success: " + response.toString()); - if (callbackArr[0] != null) { - callbackArr[0].invoke(RNUtils.jsonToWritableMap(response)); - callbackArr[0] = null; - } - } - - @Override - public void onFailure(JSONObject response) { - Log.e("OneSignal", "postNotification Failure: " + response.toString()); - if (callbackArr[1] != null) { - callbackArr[1].invoke(RNUtils.jsonToWritableMap(response)); - callbackArr[1] = null; - } - } - } - ); - } - - @ReactMethod - public void clearOneSignalNotifications() { - OneSignal.clearOneSignalNotifications(); - } - - @ReactMethod - public void removeNotification(int id) { - OneSignal.removeNotification(id); - } - - @ReactMethod - public void removeGroupedNotifications(String id) { - OneSignal.removeGroupedNotifications(id); - } - - @ReactMethod - public void requiresUserPrivacyConsent(Promise promise) { - promise.resolve(OneSignal.requiresUserPrivacyConsent()); - } - - @ReactMethod - public void setRequiresUserPrivacyConsent(Boolean required) { - OneSignal.setRequiresUserPrivacyConsent(required); - } - - @ReactMethod - public void provideUserConsent(Boolean granted) { - OneSignal.provideUserConsent(granted); - } - - @ReactMethod - public void userProvidedPrivacyConsent(Promise promise) { - promise.resolve(OneSignal.userProvidedPrivacyConsent()); - } - - @ReactMethod - public void setExternalUserId(final String externalId, final String authHashToken, final Callback callback) { - final Callback[] callbackArr = new Callback[]{ callback }; - OneSignal.setExternalUserId(externalId, authHashToken, new OneSignal.OSExternalUserIdUpdateCompletionHandler() { - @Override - public void onSuccess(JSONObject results) { - Log.i("OneSignal", "Completed setting external user id: " + externalId + "with results: " + results.toString()); - - if (callbackArr[0] != null) { - callbackArr[0].invoke(RNUtils.jsonToWritableMap(results)); - callbackArr[0] = null; - } - } - - @Override - public void onFailure(OneSignal.ExternalIdError error) { - if (callbackArr[0] != null) { - callbackArr[0].invoke(error.getMessage()); - callbackArr[0] = null; - } - } - }); - } - - @ReactMethod - public void removeExternalUserId(final Callback callback) { - final Callback[] callbackArr = new Callback[]{ callback }; - OneSignal.removeExternalUserId(new OneSignal.OSExternalUserIdUpdateCompletionHandler() { - @Override - public void onSuccess(JSONObject results) { - Log.i("OneSignal", "Completed removing external user id with results: " + results.toString()); - - if (callbackArr[0] != null) { - callbackArr[0].invoke(RNUtils.jsonToWritableMap(results)); - callbackArr[0] = null; - } - } - - @Override - public void onFailure(OneSignal.ExternalIdError error) { - if (callbackArr[0] != null) { - callbackArr[0].invoke(error.getMessage()); - callbackArr[0] = null; - } - } - }); - } - - /* notification opened / received */ - - @ReactMethod - public void setNotificationOpenedHandler() { - OneSignal.setNotificationOpenedHandler(this); - } - - @Override - public void notificationOpened(OSNotificationOpenedResult result) { - sendEvent("OneSignal-remoteNotificationOpened", RNUtils.jsonToWritableMap(result.toJSONObject())); - } - - @ReactMethod - public void setNotificationWillShowInForegroundHandler() { - OneSignal.setNotificationWillShowInForegroundHandler(new OneSignal.OSNotificationWillShowInForegroundHandler() { - @Override - public void notificationWillShowInForeground(OSNotificationReceivedEvent notificationReceivedEvent) { - OSNotification notification = notificationReceivedEvent.getNotification(); - String notificationId = notification.getNotificationId(); - notificationReceivedEventCache.put(notificationId, notificationReceivedEvent); - - sendEvent("OneSignal-notificationWillShowInForeground", RNUtils.jsonToWritableMap(notification.toJSONObject())); - } - }); - } - - @ReactMethod - public void completeNotificationEvent(final String uuid, final boolean shouldDisplay) { - OSNotificationReceivedEvent receivedEvent = notificationReceivedEventCache.get(uuid); - - if (receivedEvent == null) { - Log.e("OneSignal", "(java): could not find cached notification received event with id "+uuid); - return; - } - - if (shouldDisplay) { - receivedEvent.complete(receivedEvent.getNotification()); - } else { - receivedEvent.complete(null); - } - - notificationReceivedEventCache.remove(uuid); - } - - /** - * In-App Messaging - */ - - /* triggers */ - - @ReactMethod - public void addTrigger(String key, Object object) { - OneSignal.addTrigger(key, object); - } - - @ReactMethod - public void addTriggers(ReadableMap triggers) { - OneSignal.addTriggers(triggers.toHashMap()); - } - - @ReactMethod - public void removeTriggerForKey(String key) { - OneSignal.removeTriggerForKey(key); - } - - @ReactMethod - public void removeTriggersForKeys(ReadableArray keys) { - OneSignal.removeTriggersForKeys(RNUtils.convertReableArrayIntoStringCollection(keys)); - } - - @ReactMethod - public void getTriggerValueForKey(String key, Promise promise) { - Object val = OneSignal.getTriggerValueForKey(key); - if (val == null) { - Log.e("OneSignal", "getTriggerValueForKey: There was no value for the key: " + key); - promise.reject("No Value", "There was no value for the key: " + key); - return; - } - promise.resolve(val); - } - - /* in app message click */ - - @ReactMethod - public void setInAppMessageClickHandler() { - OneSignal.setInAppMessageClickHandler(new OneSignal.OSInAppMessageClickHandler() { - @Override - public void inAppMessageClicked(OSInAppMessageAction result) { - if (!hasSetInAppClickedHandler) { - inAppMessageActionResult = result; - return; - } - sendEvent("OneSignal-inAppMessageClicked", RNUtils.jsonToWritableMap(result.toJSONObject())); - } - }); - } - - @ReactMethod - public void initInAppMessageClickHandlerParams() { - this.hasSetInAppClickedHandler = true; - if (this.inAppMessageActionResult != null) { - this.inAppMessageClicked(this.inAppMessageActionResult); - this.inAppMessageActionResult = null; - } - } - - @Override - public void inAppMessageClicked(OSInAppMessageAction result) { - if (!this.hasSetInAppClickedHandler) { - this.inAppMessageActionResult = result; - return; - } - this.sendEvent("OneSignal-inAppMessageClicked", RNUtils.jsonToWritableMap(result.toJSONObject())); - } - - /* in app message lifecycle */ - - @ReactMethod - public void setInAppMessageLifecycleHandler() { - OneSignal.setInAppMessageLifecycleHandler(new OSInAppMessageLifecycleHandler() { - @Override - public void onWillDisplayInAppMessage(OSInAppMessage message) { - sendEvent("OneSignal-inAppMessageWillDisplay", - RNUtils.jsonToWritableMap(message.toJSONObject())); - } - @Override - public void onDidDisplayInAppMessage(OSInAppMessage message) { - sendEvent("OneSignal-inAppMessageDidDisplay", - RNUtils.jsonToWritableMap(message.toJSONObject())); - } - @Override - public void onWillDismissInAppMessage(OSInAppMessage message) { - sendEvent("OneSignal-inAppMessageWillDismiss", - RNUtils.jsonToWritableMap(message.toJSONObject())); - } - @Override - public void onDidDismissInAppMessage(OSInAppMessage message) { - sendEvent("OneSignal-inAppMessageDidDismiss", - RNUtils.jsonToWritableMap(message.toJSONObject())); - } - }); - } - - /* other IAM functions */ - - @ReactMethod - public void pauseInAppMessages(Boolean pause) { - OneSignal.pauseInAppMessages(pause); - } - - /** - * Outcomes - */ - - @ReactMethod - public void sendOutcome(final String name, final Callback callback) { - OneSignal.sendOutcome(name, new OutcomeCallback() { - @Override - public void onSuccess(OSOutcomeEvent outcomeEvent) { - if (outcomeEvent != null) { - try { - callback.invoke(RNUtils.jsonToWritableMap(outcomeEvent.toJSONObject())); - } catch (JSONException e) { - Log.e("OneSignal", "sendOutcome with name: " + name + ", failed with message: " + e.getMessage()); - } - return; - } - - Log.e("OneSignal", "sendOutcome OSOutcomeEvent is null"); - } - }); - } - - @ReactMethod - public void sendUniqueOutcome(final String name, final Callback callback) { - OneSignal.sendUniqueOutcome(name, new OutcomeCallback() { - @Override - public void onSuccess(OSOutcomeEvent outcomeEvent) { - if (outcomeEvent != null) { - try { - callback.invoke(RNUtils.jsonToWritableMap(outcomeEvent.toJSONObject())); - } catch (JSONException e) { - Log.e("OneSignal", "sendUniqueOutcome with name: " + name + ", failed with message: " + e.getMessage()); - } - return; - } - - Log.e("OneSignal", "sendUniqueOutcome OSOutcomeEvent is null"); - } - }); - } - - @ReactMethod - public void sendOutcomeWithValue(final String name, final float value, final Callback callback) { - OneSignal.sendOutcomeWithValue(name, value, new OutcomeCallback() { - @Override - public void onSuccess(OSOutcomeEvent outcomeEvent) { - if (outcomeEvent != null) { - try { - callback.invoke(RNUtils.jsonToWritableMap(outcomeEvent.toJSONObject())); - } catch (JSONException e) { - Log.e("OneSignal", "sendOutcomeWithValue with name: " + name + " and value: " + value + ", failed with message: " + e.getMessage()); - } - return; - } - - Log.e("OneSignal", "sendOutcomeWithValue OSOutcomeEvent is null"); - } - }); - } - - /** - * Native Module Overrides - */ - - @Override - public String getName() { - return "OneSignal"; - } - - @Override - public void onHostDestroy() { - removeHandlers(); - removeObservers(); - } - - @Override - public void onHostPause() { - - } - - @Override - public void onHostResume() { - initOneSignal(); - } - - @Override - public void onCatalystInstanceDestroy() { - removeHandlers(); - removeObservers(); - } - - /** - * Added for NativeEventEmitter - */ - - @ReactMethod - public void addListener(String eventName) { - // Keep: Required for RN built in Event Emitter Calls. - } - - @ReactMethod - public void removeListeners(int count) { - // Keep: Required for RN built in Event Emitter Calls. - } -} diff --git a/android/src/main/java/com/geektime/rnonesignalandroid/RNUtils.java b/android/src/main/java/com/geektime/rnonesignalandroid/RNUtils.java deleted file mode 100644 index 9af5a25d..00000000 --- a/android/src/main/java/com/geektime/rnonesignalandroid/RNUtils.java +++ /dev/null @@ -1,180 +0,0 @@ -package com.geektime.rnonesignalandroid; - -import java.util.ArrayList; -import java.util.Collection; - -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.ReadableArray; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.WritableNativeArray; -import com.facebook.react.bridge.WritableNativeMap; -import com.onesignal.OSInAppMessage; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.Iterator; - -import javax.annotation.Nullable; - -/** - * Created by danpeleg on 15/02/16. - * Copyright (c) GlobeKeeper 2014-2015 - */ -public class RNUtils { - - /** - * Converts a react native readable map into a JSON object. - * - * @param readableMap map to convert to JSON Object - * @return JSON Object that contains the readable map properties - */ - @Nullable - public static JSONObject readableMapToJson(ReadableMap readableMap) { - JSONObject jsonObject = new JSONObject(); - - if (readableMap == null) { - return null; - } - - ReadableMapKeySetIterator iterator = readableMap.keySetIterator(); - if (!iterator.hasNextKey()) { - return null; - } - - while (iterator.hasNextKey()) { - String key = iterator.nextKey(); - ReadableType readableType = readableMap.getType(key); - - try { - switch (readableType) { - case Null: - jsonObject.put(key, null); - break; - case Boolean: - jsonObject.put(key, readableMap.getBoolean(key)); - break; - case Number: - // Can be int or double. - jsonObject.put(key, readableMap.getInt(key)); - break; - case String: - jsonObject.put(key, readableMap.getString(key)); - break; - case Map: - jsonObject.put(key, readableMapToJson(readableMap.getMap(key))); - break; - case Array: - jsonObject.put(key, readableMap.getArray(key)); - default: - // Do nothing and fail silently - } - } catch (JSONException ex) { - // Do nothing and fail silently - } - } - - return jsonObject; - } - - @Nullable - public static WritableMap jsonToWritableMap(JSONObject jsonObject) { - WritableMap writableMap = new WritableNativeMap(); - - if (jsonObject == null) { - return null; - } - - - Iterator iterator = jsonObject.keys(); - if (!iterator.hasNext()) { - return null; - } - - while (iterator.hasNext()) { - String key = iterator.next(); - - try { - Object value = jsonObject.get(key); - - if (value == null) { - writableMap.putNull(key); - } else if (value instanceof Boolean) { - writableMap.putBoolean(key, (Boolean) value); - } else if (value instanceof Integer) { - writableMap.putInt(key, (Integer) value); - } else if (value instanceof Double || value instanceof Long || value instanceof Float) { - String str = String.valueOf(value); - writableMap.putDouble(key, Double.parseDouble(str)); - } else if (value instanceof String) { - writableMap.putString(key, value.toString()); - } else if (value instanceof JSONObject) { - writableMap.putMap(key, jsonToWritableMap((JSONObject) value)); - } else if (value instanceof JSONArray) { - writableMap.putArray(key, jsonArrayToWritableArray((JSONArray) value)); - } else if (value.getClass().isEnum()) { - writableMap.putString(key, value.toString()); - } - } catch (JSONException ex) { - // Do nothing and fail silently - } - } - - return writableMap; - } - - @Nullable - public static WritableArray jsonArrayToWritableArray(JSONArray jsonArray) { - WritableArray writableArray = new WritableNativeArray(); - - if (jsonArray == null) { - return null; - } - - if (jsonArray.length() <= 0) { - return null; - } - - for (int i = 0 ; i < jsonArray.length(); i++) { - try { - Object value = jsonArray.get(i); - - if (value == null) { - writableArray.pushNull(); - } else if (value instanceof Boolean) { - writableArray.pushBoolean((Boolean) value); - } else if (value instanceof Integer) { - writableArray.pushInt((Integer) value); - } else if (value instanceof Double || value instanceof Long || value instanceof Float) { - String str = String.valueOf(value); - writableArray.pushDouble(Double.parseDouble(str)); - } else if (value instanceof String) { - writableArray.pushString(value.toString()); - } else if (value instanceof JSONObject) { - writableArray.pushMap(jsonToWritableMap((JSONObject) value)); - } else if (value instanceof JSONArray) { - writableArray.pushArray(jsonArrayToWritableArray((JSONArray) value)); - } else if (value.getClass().isEnum()) { - writableArray.pushString(value.toString()); - } - } catch (JSONException e) { - // Do nothing and fail silently - } - } - - return writableArray; - } - - public static Collection convertReableArrayIntoStringCollection(ReadableArray readableArray) { - ArrayList strings = new ArrayList<>(); - for (Object object : readableArray.toArrayList()) { - if (object instanceof String) - strings.add((String) object); - } - return strings; - } -} diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java new file mode 100644 index 00000000..790bcd0f --- /dev/null +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java @@ -0,0 +1,742 @@ +/* +Modified MIT License + +Copyright 2023 OneSignal + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +1. The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +2. All copies of substantial portions of the Software may only be used in connection +with services provided by OneSignal. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Authors: + - Avishay Bar (creator) - 1/31/16 + - Brad Hesse + - Josh Kasten + - Rodrigo Gomez-Palacio + - Michael DiCioccio + - Ruslan Kesheshian +*/ + +package com.onesignal.rnonesignalandroid; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.os.Bundle; +import android.util.Log; +import com.facebook.react.bridge.Callback; +import com.facebook.react.bridge.LifecycleEventListener; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.modules.core.DeviceEventManagerModule; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.Arguments; +import com.onesignal.Continue; +import com.onesignal.OneSignal; +import com.onesignal.debug.LogLevel; +import com.onesignal.common.OneSignalWrapper; +import com.onesignal.inAppMessages.IInAppMessage; +import com.onesignal.inAppMessages.IInAppMessageClickListener; +import com.onesignal.inAppMessages.IInAppMessageClickEvent; +import com.onesignal.inAppMessages.IInAppMessageClickResult; +import com.onesignal.inAppMessages.IInAppMessageLifecycleListener; +import com.onesignal.inAppMessages.IInAppMessageWillDisplayEvent; +import com.onesignal.inAppMessages.IInAppMessageDidDisplayEvent; +import com.onesignal.inAppMessages.IInAppMessageWillDismissEvent; +import com.onesignal.inAppMessages.IInAppMessageDidDismissEvent; +import com.onesignal.notifications.INotification; +import com.onesignal.notifications.INotificationClickListener; +import com.onesignal.notifications.INotificationClickEvent; +import com.onesignal.notifications.INotificationLifecycleListener; +import com.onesignal.notifications.INotificationWillDisplayEvent; +import com.onesignal.notifications.IPermissionObserver; +import com.onesignal.user.subscriptions.IPushSubscription; +import com.onesignal.user.subscriptions.IPushSubscriptionObserver; +import com.onesignal.user.subscriptions.PushSubscriptionState; +import com.onesignal.user.subscriptions.PushSubscriptionChangedState; +import com.onesignal.user.state.UserState; +import com.onesignal.user.state.UserChangedState; +import com.onesignal.user.state.IUserStateObserver; +import org.json.JSONException; + +import java.util.HashMap; +import java.util.Map; + +public class RNOneSignal extends ReactContextBaseJavaModule implements + IPushSubscriptionObserver, + IPermissionObserver, + IUserStateObserver, + LifecycleEventListener, + INotificationLifecycleListener{ + private ReactApplicationContext mReactApplicationContext; + private ReactContext mReactContext; + + private boolean oneSignalInitDone; + private boolean hasSetPermissionObserver = false; + private boolean hasSetPushSubscriptionObserver = false; + private boolean hasSetUserStateObserver = false; + + private HashMap notificationWillDisplayCache; + private HashMap preventDefaultCache; + + private boolean hasAddedNotificationForegroundListener = false; + private boolean hasAddedInAppMessageLifecycleListener = false; + private boolean hasAddedNotificationClickListener = false; + private boolean hasAddedInAppMessageClickListener = false; + + private IInAppMessageClickListener rnInAppClickListener = new IInAppMessageClickListener() { + @Override + public void onClick(IInAppMessageClickEvent event) { + try { + sendEvent("OneSignal-inAppMessageClicked", RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageClickEventToMap(event))); + } catch (JSONException e) { + e.printStackTrace(); + } + } + }; + + private IInAppMessageLifecycleListener rnInAppLifecycleListener = new IInAppMessageLifecycleListener() { + @Override + public void onWillDisplay(IInAppMessageWillDisplayEvent event) { + try { + sendEvent("OneSignal-inAppMessageWillDisplay", RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageWillDisplayEventToMap(event))); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + @Override + public void onDidDisplay(IInAppMessageDidDisplayEvent event) { + try { + sendEvent("OneSignal-inAppMessageDidDisplay", RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageDidDisplayEventToMap(event))); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + @Override + public void onWillDismiss(IInAppMessageWillDismissEvent event) { + try { + sendEvent("OneSignal-inAppMessageWillDismiss", RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageWillDismissEventToMap(event))); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + @Override + public void onDidDismiss(IInAppMessageDidDismissEvent event) { + try { + sendEvent("OneSignal-inAppMessageDidDismiss", RNUtils.convertHashMapToWritableMap(RNUtils.convertInAppMessageDidDismissEventToMap(event))); + } catch (JSONException e) { + e.printStackTrace(); + } + } + }; + + private INotificationClickListener rnNotificationClickListener = new INotificationClickListener() { + @Override + public void onClick(INotificationClickEvent event) { + try { + sendEvent("OneSignal-notificationClicked", RNUtils.convertHashMapToWritableMap(RNUtils.convertNotificationClickEventToMap(event))); + } catch (JSONException e) { + e.printStackTrace(); + } + } + }; + + private void removeObservers() { + this.removePermissionObserver(); + this.removePushSubscriptionObserver(); + this.removeUserStateObserver(); + } + + private void removeHandlers() { + if(!oneSignalInitDone) { + Log.i("OneSignal", "OneSignal React-Native SDK not initialized yet. Could not remove handlers."); + return; + } + + OneSignal.getInAppMessages().removeClickListener(rnInAppClickListener); + hasAddedInAppMessageClickListener = false; + OneSignal.getInAppMessages().removeLifecycleListener(rnInAppLifecycleListener); + hasAddedInAppMessageLifecycleListener = false; + OneSignal.getNotifications().removeClickListener(rnNotificationClickListener); + hasAddedNotificationClickListener = false; + OneSignal.getNotifications().removeForegroundLifecycleListener(this); + hasAddedNotificationForegroundListener = false; + } + + private void sendEvent(String eventName, Object params) { + mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params); + } + + public RNOneSignal(ReactApplicationContext reactContext) { + super(reactContext); + mReactApplicationContext = reactContext; + mReactContext = reactContext; + mReactContext.addLifecycleEventListener(this); + notificationWillDisplayCache = new HashMap(); + preventDefaultCache = new HashMap(); + } + + + /** Native Module Overrides */ + @Override + public String getName() { + return "OneSignal"; + } + + @Override + public void onHostDestroy() { + removeHandlers(); + removeObservers(); + } + + @Override + public void onHostPause() {} + + @Override + public void onHostResume() {} + + @Override + public void onCatalystInstanceDestroy() { + removeHandlers(); + removeObservers(); + } + + // OneSignal namespace methods + @ReactMethod + public void initialize(String appId) { + Context context = mReactApplicationContext.getCurrentActivity(); + OneSignalWrapper.setSdkType("reactnative"); + OneSignalWrapper.setSdkVersion("050100"); + + if (oneSignalInitDone) { + Log.e("OneSignal", "Already initialized the OneSignal React-Native SDK"); + return; + } + + oneSignalInitDone = true; + + if (context == null) { + // in some cases, especially when react-native-navigation is installed, + // the activity can be null, so we can initialize with the context instead + context = mReactApplicationContext.getApplicationContext(); + } + + OneSignal.initWithContext(context, appId); + } + + @ReactMethod + public void setPrivacyConsentGiven(Boolean value) { + OneSignal.setConsentGiven(value); + } + + @ReactMethod + public void setPrivacyConsentRequired(Boolean required) { + OneSignal.setConsentRequired(required); + } + + + // OneSignal.Debug namespace methods + @ReactMethod + public void setLogLevel(int logLevel) { + OneSignal.getDebug().setLogLevel(LogLevel.fromInt(logLevel)); + } + + @ReactMethod + public void setAlertLevel(int logLevel) { + OneSignal.getDebug().setAlertLevel(LogLevel.fromInt(logLevel)); + } + + + // OneSignal.InAppMessages namespace methods + @ReactMethod + public void addInAppMessageClickListener() { + if (!hasAddedInAppMessageClickListener) { + OneSignal.getInAppMessages().addClickListener(rnInAppClickListener); + hasAddedInAppMessageClickListener = true; + } + } + + @ReactMethod + public void addInAppMessagesLifecycleListener() { + if (!hasAddedInAppMessageLifecycleListener) { + OneSignal.getInAppMessages().addLifecycleListener(rnInAppLifecycleListener); + hasAddedInAppMessageLifecycleListener = true; + } + } + + @ReactMethod + public void getPaused(Promise promise) { + promise.resolve(OneSignal.getInAppMessages().getPaused()); + } + + @ReactMethod + public void paused(Boolean pause) { + OneSignal.getInAppMessages().setPaused(pause); + } + + @ReactMethod + public void addTrigger(String key, String value) { + OneSignal.getInAppMessages().addTrigger(key, value); + } + + @ReactMethod + public void addTriggers(ReadableMap triggers) { + OneSignal.getInAppMessages().addTriggers(RNUtils.convertReadableMapIntoStringMap(triggers)); + } + + @ReactMethod + public void removeTrigger(String key) { + OneSignal.getInAppMessages().removeTrigger(key); + } + + @ReactMethod + public void removeTriggers(ReadableArray keys) { + OneSignal.getInAppMessages().removeTriggers(RNUtils.convertReadableArrayIntoStringCollection(keys)); + } + + @ReactMethod + public void clearTriggers() { + OneSignal.getInAppMessages().clearTriggers(); + } + + + // OneSignal.Location namespace methods + @ReactMethod + public void requestLocationPermission() { + OneSignal.getLocation().requestPermission(Continue.none()); + } + + @ReactMethod + public void isLocationShared(Promise promise) { + promise.resolve(OneSignal.getLocation().isShared()); + } + + @ReactMethod + public void setLocationShared(Boolean shared) { + OneSignal.getLocation().setShared(shared); + } + + + // OneSignal.Notifications namespace methods + @ReactMethod + public void addNotificationClickListener() { + if (this.hasAddedNotificationClickListener) { + return; + } + + OneSignal.getNotifications().addClickListener(rnNotificationClickListener); + hasAddedNotificationClickListener = true; + } + + @ReactMethod + public void addNotificationForegroundLifecycleListener() { + if (this.hasAddedNotificationForegroundListener) { + return; + } + + OneSignal.getNotifications().addForegroundLifecycleListener(this); + hasAddedNotificationForegroundListener = true; + } + + @Override + public void onWillDisplay(INotificationWillDisplayEvent event) { + if (!this.hasAddedNotificationForegroundListener) { + event.getNotification().display(); + } + + INotification notification = event.getNotification(); + String notificationId = notification.getNotificationId(); + notificationWillDisplayCache.put(notificationId, (INotificationWillDisplayEvent) event); + event.preventDefault(); + + try { + sendEvent("OneSignal-notificationWillDisplayInForeground", + RNUtils.convertHashMapToWritableMap( + RNUtils.convertNotificationToMap(notification))); + + try { + synchronized (event) { + while (preventDefaultCache.containsKey(notificationId)) { + event.wait(); + } + } + } catch(InterruptedException e){ + Log.e("InterruptedException" + e.toString(), null); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + + @ReactMethod + private void displayNotification(String notificationId){ + INotificationWillDisplayEvent event = notificationWillDisplayCache.get(notificationId); + if (event == null) { + Log.e("Could not find onWillDisplayNotification event for notification with id: " + notificationId, null); + return; + } + event.getNotification().display(); + } + + @ReactMethod + private void preventDefault(String notificationId) { + INotificationWillDisplayEvent event = notificationWillDisplayCache.get(notificationId); + if (event == null) { + Log.e("Could not find onWillDisplayNotification event for notification with id: " + notificationId, null); + return; + } + event.preventDefault(); + this.preventDefaultCache.put(notificationId, event); + } + + @ReactMethod + public void addPermissionObserver() { + if (!hasSetPermissionObserver) { + OneSignal.getNotifications().addPermissionObserver(this); + hasSetPermissionObserver = true; + } + } + + @ReactMethod + public void removePermissionObserver() { + if (hasSetPermissionObserver) { + OneSignal.getNotifications().removePermissionObserver(this); + hasSetPermissionObserver = false; + } + } + + @Override + public void onNotificationPermissionChange(boolean permission) { + try { + sendEvent("OneSignal-permissionChanged", RNUtils.convertHashMapToWritableMap(RNUtils.convertPermissionToMap(permission))); + Log.i("OneSignal", "sending permission change event"); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + @ReactMethod + public void requestNotificationPermission(final boolean fallbackToSettings, Promise promise) { + // if permission already exists, return early as the method call will not resolve + if (OneSignal.getNotifications().getPermission()) { + promise.resolve(true); + return; + } + + OneSignal.getNotifications().requestPermission(fallbackToSettings, Continue.with(result -> { + if (result.isSuccess()) { + promise.resolve(result.getData()); + } else { + promise.reject(result.getThrowable().getMessage()); + } + })); + } + + @ReactMethod + public void hasNotificationPermission(Promise promise) { + promise.resolve(OneSignal.getNotifications().getPermission()); + } + + @ReactMethod + public void permissionNative(Promise promise) { + if (OneSignal.getNotifications().getPermission()) { + promise.resolve(2); + } + else { + promise.resolve(1); + } + } + + @ReactMethod + public void canRequestNotificationPermission(Promise promise) { + promise.resolve(OneSignal.getNotifications().getCanRequestPermission()); + } + + @ReactMethod + public void clearAllNotifications() { + OneSignal.getNotifications().clearAllNotifications(); + } + + @ReactMethod + public void removeNotification(int id) { + OneSignal.getNotifications().removeNotification(id); + } + + @ReactMethod + public void removeGroupedNotifications(String id) { + OneSignal.getNotifications().removeGroupedNotifications(id); + } + + + // OneSignal.User.pushSubscription namespace methods + @ReactMethod + public void getPushSubscriptionId(Promise promise) { + IPushSubscription pushSubscription = OneSignal.getUser().getPushSubscription(); + String pushId = pushSubscription.getId(); + if (pushId != null && !pushId.isEmpty()){ + promise.resolve(pushId); + } else { + promise.resolve(null); + } + } + + @ReactMethod + public void getPushSubscriptionToken(Promise promise) { + IPushSubscription pushSubscription = OneSignal.getUser().getPushSubscription(); + String pushToken = pushSubscription.getToken(); + if (pushToken != null && !pushToken.isEmpty()) { + promise.resolve(pushToken); + } else { + promise.resolve(null); + } + } + + @ReactMethod + public void getOptedIn(Promise promise) { + IPushSubscription pushSubscription = OneSignal.getUser().getPushSubscription(); + promise.resolve(pushSubscription.getOptedIn()); + } + + @ReactMethod + public void optIn() { + IPushSubscription pushSubscription = OneSignal.getUser().getPushSubscription(); + pushSubscription.optIn(); + } + + @ReactMethod + public void optOut() { + IPushSubscription pushSubscription = OneSignal.getUser().getPushSubscription(); + pushSubscription.optOut(); + } + + @ReactMethod + public void addPushSubscriptionObserver() { + if (!hasSetPushSubscriptionObserver) { + OneSignal.getUser().getPushSubscription().addObserver(this); + hasSetPushSubscriptionObserver = true; + } + } + + @Override + public void onPushSubscriptionChange(PushSubscriptionChangedState pushSubscriptionChangedState) { + try { + sendEvent("OneSignal-subscriptionChanged", + RNUtils.convertHashMapToWritableMap( + RNUtils.convertPushSubscriptionChangedStateToMap(pushSubscriptionChangedState))); + Log.i("OneSignal", "sending subscription change event"); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + @ReactMethod + public void removePushSubscriptionObserver() { + if (hasSetPushSubscriptionObserver) { + OneSignal.getUser().getPushSubscription().removeObserver(this); + hasSetPushSubscriptionObserver = false; + } + } + + // OneSignal.Session namespace methods + @ReactMethod + public void addOutcome(String name) { + OneSignal.getSession().addOutcome(name); + } + + @ReactMethod + public void addUniqueOutcome(String name) { + OneSignal.getSession().addUniqueOutcome(name); + } + + @ReactMethod + public void addOutcomeWithValue(String name, float value) { + OneSignal.getSession().addOutcomeWithValue(name, value); + } + + // OneSignal.User namespace methods + @ReactMethod + public void login(String externalUserId) { + OneSignal.login(externalUserId); + } + + @ReactMethod + public void logout() { + OneSignal.logout(); + } + + @ReactMethod + public void setLanguage(String language) { + OneSignal.getUser().setLanguage(language); + } + + @ReactMethod + public void addTag(String key, String value) { + OneSignal.getUser().addTag(key, value); + } + + @ReactMethod + public void removeTag(String key) { + OneSignal.getUser().removeTag(key); + } + + @ReactMethod + public void addTags(ReadableMap tags) { + OneSignal.getUser().addTags(RNUtils.convertReadableMapIntoStringMap(tags)); + } + + @ReactMethod + public void removeTags(ReadableArray tagKeys) { + OneSignal.getUser().removeTags(RNUtils.convertReadableArrayIntoStringCollection(tagKeys)); + } + + @ReactMethod + public void getTags(Promise promise) { + Map tags = OneSignal.getUser().getTags(); + WritableMap writableTags = Arguments.createMap(); + for (Map.Entry entry : tags.entrySet()) { + writableTags.putString(entry.getKey(), entry.getValue()); + } + promise.resolve(writableTags); + } + + @ReactMethod + public void addEmail(String email, Promise promise) { + try { + OneSignal.getUser().addEmail(email); + promise.resolve(null); + } catch (Throwable t) { + promise.reject(t.getMessage()); + } + } + + @ReactMethod + public void removeEmail(String email, Promise promise) { + try { + OneSignal.getUser().removeEmail(email); + promise.resolve(null); + } catch (Throwable t) { + promise.reject(t.getMessage()); + } + } + + @ReactMethod + public void addSms(String smsNumber, Promise promise) { + try { + OneSignal.getUser().addSms(smsNumber); + promise.resolve(null); + } catch (Throwable t) { + promise.reject(t.getMessage()); + } + } + + @ReactMethod + public void removeSms(String smsNumber, Promise promise) { + try { + OneSignal.getUser().removeSms(smsNumber); + promise.resolve(null); + } catch (Throwable t) { + promise.reject(t.getMessage()); + } + } + + @ReactMethod + public void addAlias(String label, String id) { + OneSignal.getUser().addAlias(label, id); + } + + @ReactMethod + public void removeAlias(String label) { + OneSignal.getUser().removeAlias(label); + } + + @ReactMethod + public void addAliases(ReadableMap aliases) { + OneSignal.getUser().addAliases(RNUtils.convertReadableMapIntoStringMap(aliases)); + } + + @ReactMethod + public void removeAliases(ReadableArray aliasLabels) { + OneSignal.getUser().removeAliases(RNUtils.convertReadableArrayIntoStringCollection(aliasLabels)); + } + + @ReactMethod + public void getOnesignalId(Promise promise) { + String onesignalId = OneSignal.getUser().getOnesignalId(); + if (onesignalId.isEmpty()) { + onesignalId = null; + } + promise.resolve(onesignalId); + + } + + @ReactMethod + public void getExternalId(Promise promise) { + String externalId = OneSignal.getUser().getExternalId(); + if (externalId.isEmpty()) { + externalId = null; + } + promise.resolve(externalId); + } + + @ReactMethod + public void addUserStateObserver() { + if (!hasSetUserStateObserver) { + OneSignal.getUser().addObserver(this); + hasSetUserStateObserver = true; + } + } + + @Override + public void onUserStateChange(UserChangedState state) { + try { + sendEvent("OneSignal-userStateChanged", + RNUtils.convertHashMapToWritableMap( + RNUtils.convertUserChangedStateToMap(state))); + Log.i("OneSignal", "sending user state change event"); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + @ReactMethod + public void removeUserStateObserver() { + if (hasSetUserStateObserver) { + OneSignal.getUser().removeObserver(this); + hasSetUserStateObserver = false; + } + } + + /** Added for NativeEventEmitter */ + @ReactMethod + public void addListener(String eventName) { + // Keep: Required for RN built in Event Emitter Calls. + } + + @ReactMethod + public void removeListeners(int count) { + // Keep: Required for RN built in Event Emitter Calls. + } +} diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/RNUtils.java b/android/src/main/java/com/onesignal/rnonesignalandroid/RNUtils.java new file mode 100644 index 00000000..e9989b76 --- /dev/null +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/RNUtils.java @@ -0,0 +1,311 @@ +package com.onesignal.rnonesignalandroid; + +import java.util.ArrayList; +import java.util.Collection; +import com.facebook.react.bridge.Arguments; +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 com.facebook.react.bridge.WritableNativeArray; +import com.facebook.react.bridge.WritableNativeMap; + +import com.onesignal.inAppMessages.IInAppMessage; +import com.onesignal.inAppMessages.IInAppMessageClickEvent; +import com.onesignal.inAppMessages.IInAppMessageClickResult; +import com.onesignal.inAppMessages.IInAppMessageWillDisplayEvent; +import com.onesignal.inAppMessages.IInAppMessageDidDisplayEvent; +import com.onesignal.inAppMessages.IInAppMessageWillDismissEvent; +import com.onesignal.inAppMessages.IInAppMessageDidDismissEvent; +import com.onesignal.notifications.INotification; +import com.onesignal.notifications.INotificationWillDisplayEvent; +import com.onesignal.notifications.INotificationClickEvent; +import com.onesignal.notifications.INotificationClickResult; +import com.onesignal.notifications.INotificationReceivedEvent; +import com.onesignal.user.subscriptions.IPushSubscription; +import com.onesignal.user.subscriptions.PushSubscriptionState; +import com.onesignal.user.subscriptions.PushSubscriptionChangedState; +import com.onesignal.user.state.UserState; +import com.onesignal.user.state.UserChangedState; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import java.util.Iterator; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import javax.annotation.Nullable; + +public class RNUtils { + public static WritableMap convertHashMapToWritableMap(HashMap hashMap) throws JSONException { + WritableMap writableMap = Arguments.createMap(); + for (Map.Entry entry : hashMap.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + if (value instanceof String) { + writableMap.putString(key, (String) value); + } else if (value instanceof Boolean) { + writableMap.putBoolean(key, (Boolean) value); + } else if (value instanceof Integer) { + writableMap.putInt(key, (Integer) value); + } else if (value instanceof Double) { + writableMap.putDouble(key, (Double) value); + } else if (value instanceof Float) { + writableMap.putDouble(key, ((Float) value).doubleValue()); + } else if (value instanceof Long) { + writableMap.putDouble(key, ((Long) value).doubleValue()); + } else if (value instanceof HashMap) { + writableMap.putMap(key, convertHashMapToWritableMap((HashMap) value)); + } else { + writableMap.putNull(key); + } + } + return writableMap; + } + + public static HashMap convertNotificationClickEventToMap(INotificationClickEvent event) throws JSONException { + HashMap clickResultHash = new HashMap<>(); + HashMap hash = new HashMap<>(); + HashMap notificationHash = convertNotificationToMap(event.getNotification()); + INotificationClickResult clickResult = event.getResult(); + + clickResultHash.put("actionId", clickResult.getActionId()); + clickResultHash.put("url", clickResult.getUrl()); + + hash.put("notification", notificationHash); + hash.put("result", clickResultHash); + + return hash; + } + + public static HashMap convertNotificationToMap(INotification notification) throws JSONException { + HashMap notificationHash = new HashMap<>(); + notificationHash.put("androidNotificationId", notification.getAndroidNotificationId()); + + if (notification.getGroupedNotifications() != null) { + notificationHash.put("groupKey", notification.getGroupKey()); + notificationHash.put("groupMessage", notification.getGroupMessage()); + notificationHash.put("groupedNotifications", notification.getGroupedNotifications()); + } + + notificationHash.put("notificationId", notification.getNotificationId()); + notificationHash.put("title", notification.getTitle()); + + if (notification.getBody() != null) + notificationHash.put("body", notification.getBody()); + if (notification.getSmallIcon() != null) + notificationHash.put("smallIcon", notification.getSmallIcon()); + if (notification.getLargeIcon() != null) + notificationHash.put("largeIcon", notification.getLargeIcon()); + if (notification.getBigPicture() != null) + notificationHash.put("bigPicture", notification.getBigPicture()); + if (notification.getSmallIconAccentColor() != null) + notificationHash.put("smallIconAccentColor", notification.getSmallIconAccentColor()); + if (notification.getLaunchURL() != null) + notificationHash.put("launchUrl", notification.getLaunchURL()); + if (notification.getSound() != null) + notificationHash.put("sound", notification.getSound()); + if (notification.getLedColor() != null) + notificationHash.put("ledColor", notification.getLedColor()); + notificationHash.put("lockScreenVisibility", notification.getLockScreenVisibility()); + if (notification.getGroupKey() != null) + notificationHash.put("groupKey", notification.getGroupKey()); + if (notification.getGroupMessage() != null) + notificationHash.put("groupMessage", notification.getGroupMessage()); + if (notification.getFromProjectNumber() != null) + notificationHash.put("fromProjectNumber", notification.getFromProjectNumber()); + if (notification.getCollapseId() != null) + notificationHash.put("collapseId", notification.getCollapseId()); + notificationHash.put("priority", notification.getPriority()); + if (notification.getAdditionalData() != null && notification.getAdditionalData().length() > 0) + notificationHash.put("additionalData", convertJSONObjectToHashMap(notification.getAdditionalData())); + if (notification.getActionButtons() != null) { + notificationHash.put("actionButtons", notification.getActionButtons()); + } + notificationHash.put("rawPayload", notification.getRawPayload()); + + return notificationHash; + } + + private static HashMap convertInAppMessageToMap(IInAppMessage message) { + HashMap hash = new HashMap<>(); + hash.put("messageId", message.getMessageId()); + + return hash; + } + + public static HashMap convertInAppMessageWillDisplayEventToMap(IInAppMessageWillDisplayEvent event) { + HashMap hash = new HashMap<>(); + hash.put("message", convertInAppMessageToMap(event.getMessage())); + + return hash; + } + + public static HashMap convertInAppMessageDidDisplayEventToMap(IInAppMessageDidDisplayEvent event) { + HashMap hash = new HashMap<>(); + hash.put("message", convertInAppMessageToMap(event.getMessage())); + + return hash; + } + + public static HashMap convertInAppMessageWillDismissEventToMap(IInAppMessageWillDismissEvent event) { + HashMap hash = new HashMap<>(); + hash.put("message", convertInAppMessageToMap(event.getMessage())); + + return hash; + } + + public static HashMap convertInAppMessageDidDismissEventToMap(IInAppMessageDidDismissEvent event) { + HashMap hash = new HashMap<>(); + hash.put("message", convertInAppMessageToMap(event.getMessage())); + + return hash; + } + + public static HashMap convertInAppMessageClickEventToMap(IInAppMessageClickEvent event) { + HashMap resultHash = new HashMap<>(); + HashMap hash = new HashMap<>(); + IInAppMessageClickResult result = event.getResult(); + + resultHash.put("actionId", result.getActionId()); + resultHash.put("urlTarget", result.getUrlTarget()); + resultHash.put("url", result.getUrl()); + resultHash.put("closingMessage", result.getClosingMessage()); + + hash.put("result", resultHash); + hash.put("message", convertInAppMessageToMap(event.getMessage())); + + return hash; + } + + public static HashMap convertPushSubscriptionStateToMap(PushSubscriptionState state) { + HashMap hash = new HashMap<>(); + if (state.getToken() != null && !state.getToken().isEmpty()) { + hash.put("token", state.getToken()); + } else { + hash.put("token", JSONObject.NULL); + } + if (state.getId() != null && !state.getId().isEmpty()) { + hash.put("id", state.getId()); + } else { + hash.put("id", JSONObject.NULL); + } + hash.put("optedIn", state.getOptedIn()); + + return hash; + } + + public static HashMap convertUserStateToMap(UserState user) { + HashMap hash = new HashMap<>(); + + if (user.getExternalId() != null && !user.getExternalId().isEmpty()) { + hash.put("externalId", user.getExternalId()); + } + else { + hash.put("externalId", JSONObject.NULL); + } + if (user.getOnesignalId() != null && !user.getOnesignalId().isEmpty()) { + hash.put("onesignalId", user.getOnesignalId()); + } + else { + hash.put("onesignalId", JSONObject.NULL); + } + + return hash; + } + + public static HashMap convertPushSubscriptionChangedStateToMap(PushSubscriptionChangedState state) { + HashMap hash = new HashMap<>(); + hash.put("current", convertPushSubscriptionStateToMap(state.getCurrent())); + hash.put("previous", convertPushSubscriptionStateToMap(state.getPrevious())); + + return hash; + } + + public static HashMap convertUserChangedStateToMap(UserChangedState state) { + HashMap hash = new HashMap<>(); + hash.put("current", convertUserStateToMap(state.getCurrent())); + + return hash; + } + + public static HashMap convertJSONObjectToHashMap(JSONObject object) throws JSONException { + HashMap hash = new HashMap<>(); + + if (object == null || object == JSONObject.NULL) + return hash; + + Iterator keys = object.keys(); + + while (keys.hasNext()) { + String key = keys.next(); + + if (object.isNull(key)) + continue; + + Object val = object.get(key); + + if (val instanceof JSONArray) { + val = convertJSONArrayToList((JSONArray)val); + } else if (val instanceof JSONObject) { + val = convertJSONObjectToHashMap((JSONObject)val); + } + + hash.put(key, val); + } + + return hash; + } + + public static Collection convertReadableArrayIntoStringCollection(ReadableArray readableArray) { + ArrayList strings = new ArrayList<>(); + for (Object object : readableArray.toArrayList()) { + if (object instanceof String) + strings.add((String) object); + } + return strings; + } + + public static HashMap convertReadableMapIntoStringMap(ReadableMap readableMap) { + HashMap stringMap = new HashMap<>(); + ReadableMapKeySetIterator iter = readableMap.keySetIterator(); + + while (iter.hasNextKey()) { + String propKey = iter.nextKey(); + if (readableMap.getType(propKey) == ReadableType.String) { + stringMap.put(propKey, readableMap.getString(propKey)); + } + } + + return stringMap; + } + + public static HashMap convertPermissionToMap(boolean granted) { + HashMap hash = new HashMap<>(); + + hash.put("permission", granted); + + return hash; + } + + private static List convertJSONArrayToList(JSONArray array) throws JSONException { + List list = new ArrayList<>(); + + for (int i = 0; i < array.length(); i++) { + Object val = array.get(i); + + if (val instanceof JSONArray) + val = RNUtils.convertJSONArrayToList((JSONArray)val); + else if (val instanceof JSONObject) + val = convertJSONObjectToHashMap((JSONObject)val); + + list.add(val); + } + + return list; + } +} diff --git a/android/src/main/java/com/geektime/rnonesignalandroid/ReactNativeOneSignalPackage.java b/android/src/main/java/com/onesignal/rnonesignalandroid/ReactNativeOneSignalPackage.java similarity index 72% rename from android/src/main/java/com/geektime/rnonesignalandroid/ReactNativeOneSignalPackage.java rename to android/src/main/java/com/onesignal/rnonesignalandroid/ReactNativeOneSignalPackage.java index 3fd4426a..2ef245d2 100644 --- a/android/src/main/java/com/geektime/rnonesignalandroid/ReactNativeOneSignalPackage.java +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/ReactNativeOneSignalPackage.java @@ -1,4 +1,4 @@ -package com.geektime.rnonesignalandroid; +package com.onesignal.rnonesignalandroid; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.JavaScriptModule; @@ -9,21 +9,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Arrays; -/** - * Created by Avishay on 1/31/16. - */ public class ReactNativeOneSignalPackage implements ReactPackage { - - RNOneSignal mRNPushNotification; - @Override public List createNativeModules(ReactApplicationContext reactContext) { - List modules = new ArrayList<>(); - mRNPushNotification = new RNOneSignal(reactContext); - - modules.add(mRNPushNotification); - return modules; + return Arrays.asList(new RNOneSignal(reactContext)); } // Deprecated RN 0.47 diff --git a/examples/RNOneSignalTS/.watchmanconfig b/examples/RNOneSignalTS/.watchmanconfig index 9e26dfee..0967ef42 100644 --- a/examples/RNOneSignalTS/.watchmanconfig +++ b/examples/RNOneSignalTS/.watchmanconfig @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/examples/RNOneSignalTS/android/app/build.gradle b/examples/RNOneSignalTS/android/app/build.gradle index 7694cd28..506f58ca 100644 --- a/examples/RNOneSignalTS/android/app/build.gradle +++ b/examples/RNOneSignalTS/android/app/build.gradle @@ -178,6 +178,12 @@ android { } } + + // This is a workaround for problem with multiple occurrences of the same file `coroutines.pro`. + packagingOptions { + exclude 'META-INF/com.android.tools/proguard/coroutines.pro' + exclude 'META-INF/kotlinx_coroutines_core.version' + } } dependencies { diff --git a/examples/RNOneSignalTS/app.json b/examples/RNOneSignalTS/app.json index 078c507b..2fc9ba3f 100644 --- a/examples/RNOneSignalTS/app.json +++ b/examples/RNOneSignalTS/app.json @@ -1,4 +1,4 @@ { "name": "RNOneSignalTS", "displayName": "RNOneSignalTS" -} \ No newline at end of file +} diff --git a/examples/RNOneSignalTS/ios/Podfile b/examples/RNOneSignalTS/ios/Podfile index 544ab825..b33e170b 100644 --- a/examples/RNOneSignalTS/ios/Podfile +++ b/examples/RNOneSignalTS/ios/Podfile @@ -1,7 +1,7 @@ require_relative '../node_modules/react-native/scripts/react_native_pods' require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' -platform :ios, '10.0' +platform :ios, '11.0' target 'RNOneSignalTS' do config = use_native_modules! @@ -31,3 +31,11 @@ target 'RNOneSignalTS-tvOS' do # Pods for testing end end + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' + end + end +end diff --git a/examples/RNOneSignalTS/ios/Podfile.lock b/examples/RNOneSignalTS/ios/Podfile.lock index 7145de48..09fdf3c2 100644 --- a/examples/RNOneSignalTS/ios/Podfile.lock +++ b/examples/RNOneSignalTS/ios/Podfile.lock @@ -1,25 +1,39 @@ PODS: - boost-for-react-native (1.63.0) - DoubleConversion (1.1.6) - - FBLazyVector (0.64.1) - - FBReactNativeSpec (0.64.1): + - FBLazyVector (0.64.4) + - FBReactNativeSpec (0.64.4): - RCT-Folly (= 2020.01.13.00) - - RCTRequired (= 0.64.1) - - RCTTypeSafety (= 0.64.1) - - React-Core (= 0.64.1) - - React-jsi (= 0.64.1) - - ReactCommon/turbomodule/core (= 0.64.1) + - RCTRequired (= 0.64.4) + - RCTTypeSafety (= 0.64.4) + - React-Core (= 0.64.4) + - React-jsi (= 0.64.4) + - ReactCommon/turbomodule/core (= 0.64.4) - glog (0.3.5) - - OneSignalXCFramework (3.12.3): - - OneSignalXCFramework/OneSignalCore (= 3.12.3) - - OneSignalXCFramework/OneSignalExtension (= 3.12.3) - - OneSignalXCFramework/OneSignalOutcomes (= 3.12.3) - - OneSignalXCFramework/OneSignalCore (3.12.3) - - OneSignalXCFramework/OneSignalExtension (3.12.3): + - OneSignalXCFramework (5.0.0-beta-01): + - OneSignalXCFramework/OneSignalCore (= 5.0.0-beta-01) + - OneSignalXCFramework/OneSignalExtension (= 5.0.0-beta-01) + - OneSignalXCFramework/OneSignalNotifications (= 5.0.0-beta-01) + - OneSignalXCFramework/OneSignalOSCore (= 5.0.0-beta-01) + - OneSignalXCFramework/OneSignalOutcomes (= 5.0.0-beta-01) + - OneSignalXCFramework/OneSignalUser (= 5.0.0-beta-01) + - OneSignalXCFramework/OneSignalCore (5.0.0-beta-01) + - OneSignalXCFramework/OneSignalExtension (5.0.0-beta-01): - OneSignalXCFramework/OneSignalCore - OneSignalXCFramework/OneSignalOutcomes - - OneSignalXCFramework/OneSignalOutcomes (3.12.3): + - OneSignalXCFramework/OneSignalNotifications (5.0.0-beta-01): - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalExtension + - OneSignalXCFramework/OneSignalOutcomes + - OneSignalXCFramework/OneSignalOSCore (5.0.0-beta-01): + - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalOutcomes (5.0.0-beta-01): + - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalUser (5.0.0-beta-01): + - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalNotifications + - OneSignalXCFramework/OneSignalOSCore + - OneSignalXCFramework/OneSignalOutcomes - RCT-Folly (2020.01.13.00): - boost-for-react-native - DoubleConversion @@ -29,257 +43,257 @@ PODS: - boost-for-react-native - DoubleConversion - glog - - RCTRequired (0.64.1) - - RCTTypeSafety (0.64.1): - - FBLazyVector (= 0.64.1) + - RCTRequired (0.64.4) + - RCTTypeSafety (0.64.4): + - FBLazyVector (= 0.64.4) - RCT-Folly (= 2020.01.13.00) - - RCTRequired (= 0.64.1) - - React-Core (= 0.64.1) - - React (0.64.1): - - React-Core (= 0.64.1) - - React-Core/DevSupport (= 0.64.1) - - React-Core/RCTWebSocket (= 0.64.1) - - React-RCTActionSheet (= 0.64.1) - - React-RCTAnimation (= 0.64.1) - - React-RCTBlob (= 0.64.1) - - React-RCTImage (= 0.64.1) - - React-RCTLinking (= 0.64.1) - - React-RCTNetwork (= 0.64.1) - - React-RCTSettings (= 0.64.1) - - React-RCTText (= 0.64.1) - - React-RCTVibration (= 0.64.1) - - React-callinvoker (0.64.1) - - React-Core (0.64.1): + - RCTRequired (= 0.64.4) + - React-Core (= 0.64.4) + - React (0.64.4): + - React-Core (= 0.64.4) + - React-Core/DevSupport (= 0.64.4) + - React-Core/RCTWebSocket (= 0.64.4) + - React-RCTActionSheet (= 0.64.4) + - React-RCTAnimation (= 0.64.4) + - React-RCTBlob (= 0.64.4) + - React-RCTImage (= 0.64.4) + - React-RCTLinking (= 0.64.4) + - React-RCTNetwork (= 0.64.4) + - React-RCTSettings (= 0.64.4) + - React-RCTText (= 0.64.4) + - React-RCTVibration (= 0.64.4) + - React-callinvoker (0.64.4) + - React-Core (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - - React-Core/Default (= 0.64.1) - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-Core/Default (= 0.64.4) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/CoreModulesHeaders (0.64.1): + - React-Core/CoreModulesHeaders (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/Default (0.64.1): + - React-Core/Default (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/DevSupport (0.64.1): + - React-Core/DevSupport (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - - React-Core/Default (= 0.64.1) - - React-Core/RCTWebSocket (= 0.64.1) - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-jsinspector (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-Core/Default (= 0.64.4) + - React-Core/RCTWebSocket (= 0.64.4) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-jsinspector (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/RCTActionSheetHeaders (0.64.1): + - React-Core/RCTActionSheetHeaders (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/RCTAnimationHeaders (0.64.1): + - React-Core/RCTAnimationHeaders (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/RCTBlobHeaders (0.64.1): + - React-Core/RCTBlobHeaders (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/RCTImageHeaders (0.64.1): + - React-Core/RCTImageHeaders (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/RCTLinkingHeaders (0.64.1): + - React-Core/RCTLinkingHeaders (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/RCTNetworkHeaders (0.64.1): + - React-Core/RCTNetworkHeaders (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/RCTSettingsHeaders (0.64.1): + - React-Core/RCTSettingsHeaders (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/RCTTextHeaders (0.64.1): + - React-Core/RCTTextHeaders (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/RCTVibrationHeaders (0.64.1): + - React-Core/RCTVibrationHeaders (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-Core/RCTWebSocket (0.64.1): + - React-Core/RCTWebSocket (0.64.4): - glog - RCT-Folly (= 2020.01.13.00) - - React-Core/Default (= 0.64.1) - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsiexecutor (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-Core/Default (= 0.64.4) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsiexecutor (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga - - React-CoreModules (0.64.1): - - FBReactNativeSpec (= 0.64.1) + - React-CoreModules (0.64.4): + - FBReactNativeSpec (= 0.64.4) - RCT-Folly (= 2020.01.13.00) - - RCTTypeSafety (= 0.64.1) - - React-Core/CoreModulesHeaders (= 0.64.1) - - React-jsi (= 0.64.1) - - React-RCTImage (= 0.64.1) - - ReactCommon/turbomodule/core (= 0.64.1) - - React-cxxreact (0.64.1): + - RCTTypeSafety (= 0.64.4) + - React-Core/CoreModulesHeaders (= 0.64.4) + - React-jsi (= 0.64.4) + - React-RCTImage (= 0.64.4) + - ReactCommon/turbomodule/core (= 0.64.4) + - React-cxxreact (0.64.4): - boost-for-react-native (= 1.63.0) - DoubleConversion - glog - RCT-Folly (= 2020.01.13.00) - - React-callinvoker (= 0.64.1) - - React-jsi (= 0.64.1) - - React-jsinspector (= 0.64.1) - - React-perflogger (= 0.64.1) - - React-runtimeexecutor (= 0.64.1) - - React-jsi (0.64.1): + - React-callinvoker (= 0.64.4) + - React-jsi (= 0.64.4) + - React-jsinspector (= 0.64.4) + - React-perflogger (= 0.64.4) + - React-runtimeexecutor (= 0.64.4) + - React-jsi (0.64.4): - boost-for-react-native (= 1.63.0) - DoubleConversion - glog - RCT-Folly (= 2020.01.13.00) - - React-jsi/Default (= 0.64.1) - - React-jsi/Default (0.64.1): + - React-jsi/Default (= 0.64.4) + - React-jsi/Default (0.64.4): - boost-for-react-native (= 1.63.0) - DoubleConversion - glog - RCT-Folly (= 2020.01.13.00) - - React-jsiexecutor (0.64.1): + - React-jsiexecutor (0.64.4): - DoubleConversion - glog - RCT-Folly (= 2020.01.13.00) - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-perflogger (= 0.64.1) - - React-jsinspector (0.64.1) - - react-native-onesignal (4.4.1): - - OneSignalXCFramework (= 3.12.3) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-perflogger (= 0.64.4) + - React-jsinspector (0.64.4) + - react-native-onesignal (4.5.0): + - OneSignalXCFramework (= 5.0.0-beta-01) - React (< 1.0.0, >= 0.13.0) - - React-perflogger (0.64.1) - - React-RCTActionSheet (0.64.1): - - React-Core/RCTActionSheetHeaders (= 0.64.1) - - React-RCTAnimation (0.64.1): - - FBReactNativeSpec (= 0.64.1) + - React-perflogger (0.64.4) + - React-RCTActionSheet (0.64.4): + - React-Core/RCTActionSheetHeaders (= 0.64.4) + - React-RCTAnimation (0.64.4): + - FBReactNativeSpec (= 0.64.4) - RCT-Folly (= 2020.01.13.00) - - RCTTypeSafety (= 0.64.1) - - React-Core/RCTAnimationHeaders (= 0.64.1) - - React-jsi (= 0.64.1) - - ReactCommon/turbomodule/core (= 0.64.1) - - React-RCTBlob (0.64.1): - - FBReactNativeSpec (= 0.64.1) + - RCTTypeSafety (= 0.64.4) + - React-Core/RCTAnimationHeaders (= 0.64.4) + - React-jsi (= 0.64.4) + - ReactCommon/turbomodule/core (= 0.64.4) + - React-RCTBlob (0.64.4): + - FBReactNativeSpec (= 0.64.4) - RCT-Folly (= 2020.01.13.00) - - React-Core/RCTBlobHeaders (= 0.64.1) - - React-Core/RCTWebSocket (= 0.64.1) - - React-jsi (= 0.64.1) - - React-RCTNetwork (= 0.64.1) - - ReactCommon/turbomodule/core (= 0.64.1) - - React-RCTImage (0.64.1): - - FBReactNativeSpec (= 0.64.1) + - React-Core/RCTBlobHeaders (= 0.64.4) + - React-Core/RCTWebSocket (= 0.64.4) + - React-jsi (= 0.64.4) + - React-RCTNetwork (= 0.64.4) + - ReactCommon/turbomodule/core (= 0.64.4) + - React-RCTImage (0.64.4): + - FBReactNativeSpec (= 0.64.4) - RCT-Folly (= 2020.01.13.00) - - RCTTypeSafety (= 0.64.1) - - React-Core/RCTImageHeaders (= 0.64.1) - - React-jsi (= 0.64.1) - - React-RCTNetwork (= 0.64.1) - - ReactCommon/turbomodule/core (= 0.64.1) - - React-RCTLinking (0.64.1): - - FBReactNativeSpec (= 0.64.1) - - React-Core/RCTLinkingHeaders (= 0.64.1) - - React-jsi (= 0.64.1) - - ReactCommon/turbomodule/core (= 0.64.1) - - React-RCTNetwork (0.64.1): - - FBReactNativeSpec (= 0.64.1) + - RCTTypeSafety (= 0.64.4) + - React-Core/RCTImageHeaders (= 0.64.4) + - React-jsi (= 0.64.4) + - React-RCTNetwork (= 0.64.4) + - ReactCommon/turbomodule/core (= 0.64.4) + - React-RCTLinking (0.64.4): + - FBReactNativeSpec (= 0.64.4) + - React-Core/RCTLinkingHeaders (= 0.64.4) + - React-jsi (= 0.64.4) + - ReactCommon/turbomodule/core (= 0.64.4) + - React-RCTNetwork (0.64.4): + - FBReactNativeSpec (= 0.64.4) - RCT-Folly (= 2020.01.13.00) - - RCTTypeSafety (= 0.64.1) - - React-Core/RCTNetworkHeaders (= 0.64.1) - - React-jsi (= 0.64.1) - - ReactCommon/turbomodule/core (= 0.64.1) - - React-RCTSettings (0.64.1): - - FBReactNativeSpec (= 0.64.1) + - RCTTypeSafety (= 0.64.4) + - React-Core/RCTNetworkHeaders (= 0.64.4) + - React-jsi (= 0.64.4) + - ReactCommon/turbomodule/core (= 0.64.4) + - React-RCTSettings (0.64.4): + - FBReactNativeSpec (= 0.64.4) - RCT-Folly (= 2020.01.13.00) - - RCTTypeSafety (= 0.64.1) - - React-Core/RCTSettingsHeaders (= 0.64.1) - - React-jsi (= 0.64.1) - - ReactCommon/turbomodule/core (= 0.64.1) - - React-RCTText (0.64.1): - - React-Core/RCTTextHeaders (= 0.64.1) - - React-RCTVibration (0.64.1): - - FBReactNativeSpec (= 0.64.1) + - RCTTypeSafety (= 0.64.4) + - React-Core/RCTSettingsHeaders (= 0.64.4) + - React-jsi (= 0.64.4) + - ReactCommon/turbomodule/core (= 0.64.4) + - React-RCTText (0.64.4): + - React-Core/RCTTextHeaders (= 0.64.4) + - React-RCTVibration (0.64.4): + - FBReactNativeSpec (= 0.64.4) - RCT-Folly (= 2020.01.13.00) - - React-Core/RCTVibrationHeaders (= 0.64.1) - - React-jsi (= 0.64.1) - - ReactCommon/turbomodule/core (= 0.64.1) - - React-runtimeexecutor (0.64.1): - - React-jsi (= 0.64.1) - - ReactCommon/turbomodule/core (0.64.1): + - React-Core/RCTVibrationHeaders (= 0.64.4) + - React-jsi (= 0.64.4) + - ReactCommon/turbomodule/core (= 0.64.4) + - React-runtimeexecutor (0.64.4): + - React-jsi (= 0.64.4) + - ReactCommon/turbomodule/core (0.64.4): - DoubleConversion - glog - RCT-Folly (= 2020.01.13.00) - - React-callinvoker (= 0.64.1) - - React-Core (= 0.64.1) - - React-cxxreact (= 0.64.1) - - React-jsi (= 0.64.1) - - React-perflogger (= 0.64.1) + - React-callinvoker (= 0.64.4) + - React-Core (= 0.64.4) + - React-cxxreact (= 0.64.4) + - React-jsi (= 0.64.4) + - React-perflogger (= 0.64.4) - Yoga (1.14.0) DEPENDENCIES: @@ -383,36 +397,36 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de - FBLazyVector: 7b423f9e248eae65987838148c36eec1dbfe0b53 - FBReactNativeSpec: 24caa029596b15294bf7ac235d35b59765ae5469 + FBLazyVector: fa8275d5086566e22a26ddc385ab5772e7f9b1bd + FBReactNativeSpec: 799cb1402acc2a3e73cb23b36dae1513cd34e35d glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62 - OneSignalXCFramework: 75844c29607ca95e6176f6f21257b4382c7fdbfb + OneSignalXCFramework: 7d3eb90c3e78908b0d72aa88600bfdab694460ec RCT-Folly: ec7a233ccc97cc556cf7237f0db1ff65b986f27c - RCTRequired: ec2ebc96b7bfba3ca5c32740f5a0c6a014a274d2 - RCTTypeSafety: 22567f31e67c3e088c7ac23ea46ab6d4779c0ea5 - React: a241e3dbb1e91d06332f1dbd2b3ab26e1a4c4b9d - React-callinvoker: da4d1c6141696a00163960906bc8a55b985e4ce4 - React-Core: 46ba164c437d7dac607b470c83c8308b05799748 - React-CoreModules: 217bd14904491c7b9940ff8b34a3fe08013c2f14 - React-cxxreact: 0090588ae6660c4615d3629fdd5c768d0983add4 - React-jsi: 5de8204706bd872b78ea646aee5d2561ca1214b6 - React-jsiexecutor: 124e8f99992490d0d13e0649d950d3e1aae06fe9 - React-jsinspector: 500a59626037be5b3b3d89c5151bc3baa9abf1a9 - react-native-onesignal: 422286fc3ac6db94e7d568a1b41d9db411a1d3c7 - React-perflogger: aad6d4b4a267936b3667260d1f649b6f6069a675 - React-RCTActionSheet: fc376be462c9c8d6ad82c0905442fd77f82a9d2a - React-RCTAnimation: ba0a1c3a2738be224a08092fa7f1b444ab77d309 - React-RCTBlob: f758d4403fc5828a326dc69e27b41e1a92f34947 - React-RCTImage: ce57088705f4a8d03f6594b066a59c29143ba73e - React-RCTLinking: 852a3a95c65fa63f657a4b4e2d3d83a815e00a7c - React-RCTNetwork: 9d7ccb8a08d522d71700b4fb677d9fa28cccd118 - React-RCTSettings: d8aaf4389ff06114dee8c42ef5f0f2915946011e - React-RCTText: 809c12ed6b261796ba056c04fcd20d8b90bcc81d - React-RCTVibration: 4b99a7f5c6c0abbc5256410cc5425fb8531986e1 - React-runtimeexecutor: ff951a0c241bfaefc4940a3f1f1a229e7cb32fa6 - ReactCommon: bedc99ed4dae329c4fcf128d0c31b9115e5365ca - Yoga: a7de31c64fe738607e7a3803e3f591a4b1df7393 + RCTRequired: f85fa00af016059cf88b90b8f8ff9a6af9e4b6c3 + RCTTypeSafety: 5279aaf0fb1ad715cbbbbee32d5c98c72598bc9c + React: ff4e89fbcb05461c9533fd4da3c0f44cda6ab618 + React-callinvoker: 4670ac7842699e4a39b19a08b4ede02573c1e5dd + React-Core: ee61e8a8aea912e1504ebec230b3e07d96cf82e1 + React-CoreModules: 8544ba0d319003b33707cdeed66e3122685d31a0 + React-cxxreact: 668500d4ce359515bbf8f907bca0e66fd357d36f + React-jsi: 64f80675a66899bf0f4a58b8e3908966fa516234 + React-jsiexecutor: 8c077bef1c64430b6034f27df1000d194551e2eb + React-jsinspector: d4f6973dd474357dbaaf6f52f31ffc713bf3e766 + react-native-onesignal: 039457cc04ef4e56c30069c4f3a1f3e893986abf + React-perflogger: 5a890ca0911669421b7611661e9b58f91c805f5c + React-RCTActionSheet: bd180e0879f8424a73650c5c28fbef4f3b5b27fb + React-RCTAnimation: 1004d2b4be1f2cedfdc4cb2326adc95b989e6c6b + React-RCTBlob: 55a984137d10e4c41071e8d39374336b48656e54 + React-RCTImage: fa346c899c2f7301eddc79860c37f836db185eb2 + React-RCTLinking: 7af1444a261610ff29a1afeab8c1cfcb5c3280a9 + React-RCTNetwork: fdaad596311091a2c48e0327b8431ba3e011a684 + React-RCTSettings: a7879d48e2951d107763f53e1db80be29f462ab7 + React-RCTText: d7e66b2600487f631531f77bb9d336e33c1187d9 + React-RCTVibration: 761849eea2a1abc99d5e4171bae17ab3da3143ac + React-runtimeexecutor: 5b441857030bb6c3abaa7517f333cb01875ae499 + ReactCommon: b4a65d2d6e9eeffd4b32dde1245962b3f43907d0 + Yoga: d1fc3575b8b68891ff5ef3c276daa855e841eb32 -PODFILE CHECKSUM: ee2174551b18176b5f22df017388e28988664cb8 +PODFILE CHECKSUM: f9cd8e12615dff6738f284cf82df8cb563bf51cf COCOAPODS: 1.11.3 diff --git a/examples/RNOneSignalTS/ios/RNOneSignalTS.xcodeproj/project.pbxproj b/examples/RNOneSignalTS/ios/RNOneSignalTS.xcodeproj/project.pbxproj index 5feb6a7f..4ce04e86 100644 --- a/examples/RNOneSignalTS/ios/RNOneSignalTS.xcodeproj/project.pbxproj +++ b/examples/RNOneSignalTS/ios/RNOneSignalTS.xcodeproj/project.pbxproj @@ -211,7 +211,7 @@ 00E356EB1AD99517003FC87E /* Frameworks */, 00E356EC1AD99517003FC87E /* Resources */, 985973970AD5AD54BC615F13 /* [CP] Copy Pods Resources */, - 0D3C4A67F609AD5AE123C9B5 /* [CP] Embed Pods Frameworks */, + 334D46447F1AE58B86D6B464 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -234,7 +234,7 @@ 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 258A29E138A5D5C56B8AB2B5 /* [CP] Copy Pods Resources */, - 680D6FE20D3CFD9E80BCC3D2 /* [CP] Embed Pods Frameworks */, + BF08836FBCCF6DF73FFD31DC /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -384,30 +384,6 @@ shellPath = /bin/sh; shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; }; - 0D3C4A67F609AD5AE123C9B5 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RNOneSignalTS-RNOneSignalTSTests/Pods-RNOneSignalTS-RNOneSignalTSTests-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignal.framework/OneSignal", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalCore/OneSignalCore.framework/OneSignalCore", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalExtension/OneSignalExtension.framework/OneSignalExtension", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalOutcomes/OneSignalOutcomes.framework/OneSignalOutcomes", - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignal.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalCore.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalExtension.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalOutcomes.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNOneSignalTS-RNOneSignalTSTests/Pods-RNOneSignalTS-RNOneSignalTSTests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; 0FEF11F60825F2FC61B8C711 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -484,50 +460,56 @@ shellPath = /bin/sh; shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; }; - 557BD3371D7E9F41213BB1E8 /* [CP] Check Pods Manifest.lock */ = { + 334D46447F1AE58B86D6B464 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNOneSignalTS-RNOneSignalTSTests/Pods-RNOneSignalTS-RNOneSignalTSTests-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalFramework.framework/OneSignalFramework", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalCore/OneSignalCore.framework/OneSignalCore", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalExtension/OneSignalExtension.framework/OneSignalExtension", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalNotifications/OneSignalNotifications.framework/OneSignalNotifications", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalOSCore/OneSignalOSCore.framework/OneSignalOSCore", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalOutcomes/OneSignalOutcomes.framework/OneSignalOutcomes", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalUser/OneSignalUser.framework/OneSignalUser", ); + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RNOneSignalTS-checkManifestLockResult.txt", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalFramework.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalCore.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalExtension.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalNotifications.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalOSCore.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalOutcomes.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalUser.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNOneSignalTS-RNOneSignalTSTests/Pods-RNOneSignalTS-RNOneSignalTSTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 680D6FE20D3CFD9E80BCC3D2 /* [CP] Embed Pods Frameworks */ = { + 557BD3371D7E9F41213BB1E8 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RNOneSignalTS/Pods-RNOneSignalTS-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignal.framework/OneSignal", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalCore/OneSignalCore.framework/OneSignalCore", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalExtension/OneSignalExtension.framework/OneSignalExtension", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalOutcomes/OneSignalOutcomes.framework/OneSignalOutcomes", + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignal.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalCore.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalExtension.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalOutcomes.framework", + "$(DERIVED_FILE_DIR)/Pods-RNOneSignalTS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNOneSignalTS/Pods-RNOneSignalTS-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 7C5D09C9CEB1208DFD72EAEA /* [CP] Check Pods Manifest.lock */ = { @@ -570,6 +552,36 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNOneSignalTS-RNOneSignalTSTests/Pods-RNOneSignalTS-RNOneSignalTSTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; + BF08836FBCCF6DF73FFD31DC /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNOneSignalTS/Pods-RNOneSignalTS-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalFramework.framework/OneSignalFramework", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalCore/OneSignalCore.framework/OneSignalCore", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalExtension/OneSignalExtension.framework/OneSignalExtension", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalNotifications/OneSignalNotifications.framework/OneSignalNotifications", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalOSCore/OneSignalOSCore.framework/OneSignalOSCore", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalOutcomes/OneSignalOutcomes.framework/OneSignalOutcomes", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OneSignalXCFramework/OneSignalUser/OneSignalUser.framework/OneSignalUser", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalFramework.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalCore.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalExtension.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalNotifications.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalOSCore.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalOutcomes.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OneSignalUser.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNOneSignalTS/Pods-RNOneSignalTS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; FD10A7F022414F080027D42C /* Start Packager */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -672,7 +684,7 @@ "$(inherited)", ); INFOPLIST_FILE = RNOneSignalTSTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; OTHER_LDFLAGS = ( "-ObjC", @@ -693,7 +705,7 @@ COPY_PHASE_STRIP = NO; DEVELOPMENT_TEAM = 99SW8E36CT; INFOPLIST_FILE = RNOneSignalTSTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; OTHER_LDFLAGS = ( "-ObjC", @@ -723,7 +735,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = com.testapp.rodrigo; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example; PRODUCT_NAME = RNOneSignalTS; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -747,7 +759,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = com.testapp.rodrigo; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example; PRODUCT_NAME = RNOneSignalTS; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -836,7 +848,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RNOneSignalTS-tvOS.app/RNOneSignalTS-tvOS"; - TVOS_DEPLOYMENT_TARGET = 10.1; + TVOS_DEPLOYMENT_TARGET = 11.0; }; name = Debug; }; @@ -864,7 +876,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RNOneSignalTS-tvOS.app/RNOneSignalTS-tvOS"; - TVOS_DEPLOYMENT_TARGET = 10.1; + TVOS_DEPLOYMENT_TARGET = 11.0; }; name = Release; }; @@ -915,7 +927,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; LIBRARY_SEARCH_PATHS = ( "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", @@ -968,7 +980,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; LIBRARY_SEARCH_PATHS = ( "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", diff --git a/examples/RNOneSignalTS/ios/RNOneSignalTS.xcodeproj/xcshareddata/xcschemes/RNOneSignalTS-tvOS.xcscheme b/examples/RNOneSignalTS/ios/RNOneSignalTS.xcodeproj/xcshareddata/xcschemes/RNOneSignalTS-tvOS.xcscheme index aa601f92..e921e283 100644 --- a/examples/RNOneSignalTS/ios/RNOneSignalTS.xcodeproj/xcshareddata/xcschemes/RNOneSignalTS-tvOS.xcscheme +++ b/examples/RNOneSignalTS/ios/RNOneSignalTS.xcodeproj/xcshareddata/xcschemes/RNOneSignalTS-tvOS.xcscheme @@ -1,6 +1,6 @@ + NSLocationAlwaysAndWhenInUseUsageDescription + Your message goes here + NSLocationAlwaysUsageDescription + Your message goes here NSLocationUsageDescription Your message goes here NSLocationWhenInUseUsageDescription - Your message goes here - NSLocationAlwaysAndWhenInUseUsageDescription Your message goes here - NSLocationAlwaysUsageDescription - Your message goes here UIBackgroundModes remote-notification diff --git a/examples/RNOneSignalTS/package.json b/examples/RNOneSignalTS/package.json index d2c4be78..915209a2 100644 --- a/examples/RNOneSignalTS/package.json +++ b/examples/RNOneSignalTS/package.json @@ -10,16 +10,17 @@ "lint": "eslint . --ext .js,.jsx,.ts,.tsx" }, "dependencies": { - "react": "16.13.1", - "react-native": "0.64.1", - "react-native-onesignal": "^4.5.2" + "@react-native-material/core": "^1.3.7", + "react": "17.0.1", + "react-native": "0.64.4", + "react-native-onesignal": "file:../../" }, "devDependencies": { "@babel/core": "^7.8.4", "@babel/runtime": "^7.8.4", "@react-native-community/eslint-config": "^1.1.0", "@types/jest": "^25.2.3", - "@types/react-native": "^0.63.2", + "@types/react-native": "^0.64.4", "@types/react-test-renderer": "^16.9.2", "@typescript-eslint/eslint-plugin": "^2.27.0", "@typescript-eslint/parser": "^2.27.0", @@ -27,7 +28,7 @@ "eslint": "^6.5.1", "jest": "^25.1.0", "metro-react-native-babel-preset": "^0.59.0", - "react-test-renderer": "16.13.1", + "react-test-renderer": "17.0.1", "typescript": "^3.8.3" }, "jest": { diff --git a/examples/RNOneSignalTS/src/App.tsx b/examples/RNOneSignalTS/src/App.tsx index fe9efedf..d4d8beea 100644 --- a/examples/RNOneSignalTS/src/App.tsx +++ b/examples/RNOneSignalTS/src/App.tsx @@ -17,9 +17,7 @@ import { StatusBar, } from 'react-native'; -import { - Colors -} from 'react-native/Libraries/NewAppScreen'; +import {Colors} from 'react-native/Libraries/NewAppScreen'; import OSDemo from './OSDemo'; declare const global: {HermesInternal: null | {}}; @@ -28,55 +26,18 @@ const App = () => { return ( <> - - - - - - - + + + ); }; const styles = StyleSheet.create({ - scrollView: { - backgroundColor: Colors.lighter, - }, - engine: { - position: 'absolute', - right: 0, - }, body: { + flex: 1, backgroundColor: Colors.white, - }, - sectionContainer: { - marginTop: 32, - paddingHorizontal: 24, - }, - sectionTitle: { - fontSize: 24, - fontWeight: '600', - color: Colors.black, - }, - sectionDescription: { - marginTop: 8, - fontSize: 18, - fontWeight: '400', - color: Colors.dark, - }, - highlight: { - fontWeight: '700', - }, - footer: { - color: Colors.dark, - fontSize: 12, - fontWeight: '600', - padding: 4, - paddingRight: 12, - textAlign: 'right', + padding: 10, }, }); diff --git a/examples/RNOneSignalTS/src/Helpers.tsx b/examples/RNOneSignalTS/src/Helpers.tsx index d1fd266c..43406953 100644 --- a/examples/RNOneSignalTS/src/Helpers.tsx +++ b/examples/RNOneSignalTS/src/Helpers.tsx @@ -1,64 +1,72 @@ import * as React from 'react'; -import { Button, View, StyleSheet, Platform, KeyboardAvoidingView, TextInput } from "react-native"; -const disabledColor = '#BEBEBE'; +import { + View, + StyleSheet, + Platform, + KeyboardAvoidingView, + TextInput, +} from 'react-native'; +import {Button} from '@react-native-material/core'; -export const renderButtonView = (name: string, color: string, callback: Function) => { - return ( - -