├── .bundle └── config ├── .circleci └── config.yml ├── .editorconfig ├── .gitattributes ├── .github ├── labeler.yml └── workflows │ └── labeler.yml ├── .gitignore ├── .node-version ├── .nvmrc ├── .refactorer └── config.md ├── .ruby-version ├── .yarnrc ├── CONTRIBUTING.md ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── REPO_OWNER ├── android ├── app │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── rndiffapp │ │ │ └── newarchitecture │ │ │ ├── MainApplicationReactNativeHost.java │ │ │ ├── components │ │ │ └── MainComponentsRegistry.java │ │ │ └── modules │ │ │ └── MainApplicationTurboModuleManagerDelegate.java │ │ ├── jni │ │ ├── CMakeLists.txt │ │ ├── MainApplicationModuleProvider.cpp │ │ ├── MainApplicationModuleProvider.h │ │ ├── MainApplicationTurboModuleManagerDelegate.cpp │ │ ├── MainApplicationTurboModuleManagerDelegate.h │ │ ├── MainComponentsRegistry.cpp │ │ ├── MainComponentsRegistry.h │ │ └── OnLoad.cpp │ │ └── res │ │ └── drawable │ │ └── rn_edit_text_material.xml ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ ├── com │ └── intercom │ │ └── reactnative │ │ ├── IntercomErrorCodes.java │ │ ├── IntercomEventEmitter.java │ │ ├── IntercomHelpCenterHelpers.java │ │ ├── IntercomHelpers.java │ │ ├── IntercomModule.java │ │ ├── IntercomPackage.java │ │ └── RNIntercomPushBroadcastReceiver.java │ └── io │ └── intercom │ └── android │ └── sdk │ └── api │ └── ReactNativeHeaderInterceptor.java ├── app.plugin.js ├── babel.config.js ├── docs ├── IOS-MANUAL-LINKING.md ├── scheme-setup.png ├── xcode-linking.png └── xcode-popup.png ├── example ├── .env.example ├── README.md ├── android │ ├── app │ │ ├── build.gradle │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── intercomreactnative │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── play │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── intercomreactnative │ │ │ └── MainNotificationService.java │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── assets │ └── intercom.png ├── babel.config.js ├── e2e │ ├── helpers.ts │ ├── package-lock.json │ ├── package.json │ ├── tests │ │ └── mainIntercom.e2e.ts │ ├── types │ │ └── wido.d.ts │ ├── wdio.android.conf.ts │ ├── wdio.ios.conf.ts │ └── yarn.lock ├── index.tsx ├── ios │ ├── File.swift │ ├── IntercomReactNativeExample-Bridging-Header.h │ ├── IntercomReactNativeExample.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── IntercomReactNativeExample.xcscheme │ │ │ └── IntercomReactNativeExampleUI.xcscheme │ ├── IntercomReactNativeExample.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── IntercomReactNativeExample │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── IntercomReactNativeExample.entitlements │ │ ├── IntercomReactNativeExampleRelease.entitlements │ │ ├── LaunchScreen.storyboard │ │ └── main.m │ ├── IntercomReactNativeExampleUIRelease.entitlements │ ├── Podfile │ ├── Podfile.lock │ └── PrivacyInfo.xcprivacy ├── metro.config.js ├── package-lock.json ├── package.json ├── scripts │ └── generateEnv.sh ├── src │ ├── App.tsx │ ├── components │ │ ├── Button.tsx │ │ └── Input.tsx │ └── constants.tsx └── yarn.lock ├── intercom-react-native.podspec ├── ios ├── .xcode.env ├── Intercom.xcodeproj │ └── project.pbxproj ├── IntercomAttributesBuilder.h ├── IntercomAttributesBuilder.m ├── IntercomEventEmitter.h ├── IntercomEventEmitter.m ├── IntercomHelpCenterHelpers.h ├── IntercomHelpCenterHelpers.m ├── IntercomModule.h └── IntercomModule.m ├── package.json ├── sandboxes ├── IntercomExpo │ ├── .gitignore │ ├── App.js │ ├── App.styles.js │ ├── App.utils.js │ ├── README.md │ ├── app.json │ ├── assets │ │ ├── adaptive-icon.png │ │ ├── favicon.png │ │ ├── icon.png │ │ └── splash.png │ ├── babel.config.js │ ├── package-lock.json │ ├── package.json │ ├── useIntercom.js │ └── yarn.lock └── NotificationsSandbox │ ├── .bundle │ └── config │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc.js │ ├── .watchmanconfig │ ├── App.styles.ts │ ├── App.tsx │ ├── App.utils.ts │ ├── Gemfile │ ├── Gemfile.lock │ ├── HomeScreen.tsx │ ├── README.md │ ├── SettingsScreen.tsx │ ├── android │ ├── app │ │ ├── build.gradle │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── sample │ │ │ │ ├── MainActivity.kt │ │ │ │ └── MainApplication.kt │ │ │ └── res │ │ │ ├── drawable │ │ │ └── rn_edit_text_material.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle │ ├── app.json │ ├── babel.config.js │ ├── index.js │ ├── ios │ ├── .xcode.env │ ├── Podfile │ ├── Podfile.lock │ ├── notificationsandbox.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── notificationsandbox.xcscheme │ ├── notificationsandbox.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── notificationsandbox │ │ ├── AppDelegate.h │ │ ├── AppDelegate.mm │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ ├── PrivacyInfo.xcprivacy │ │ ├── main.m │ │ └── notificationsandbox.entitlements │ └── notificationsandboxTests │ │ ├── Info.plist │ │ └── notificationsandboxTests.m │ ├── jest.config.js │ ├── metro.config.js │ ├── package.json │ ├── payload.apns │ ├── payload.json │ ├── tsconfig.json │ ├── useIntercom.tsx │ └── yarn.lock ├── script └── setup ├── scripts └── bootstrap.js ├── src ├── expo-plugins │ ├── @types.ts │ ├── index.ts │ └── withPushNotifications.ts └── index.tsx ├── tsconfig.build.json ├── tsconfig.json └── yarn.lock /.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | indent_style = space 10 | indent_size = 2 11 | 12 | end_of_line = lf 13 | charset = utf-8 14 | trim_trailing_whitespace = true 15 | insert_final_newline = true 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | # specific for windows script files 3 | *.bat text eol=crlf 4 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | team-messenger: 2 | - base-branch: 'main' 3 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Labeler" 2 | on: 3 | - pull_request_target 4 | 5 | jobs: 6 | labeler: 7 | permissions: 8 | contents: read 9 | pull-requests: write 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/labeler@v5 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # XDE 6 | .expo/ 7 | 8 | # VSCode 9 | .vscode/ 10 | jsconfig.json 11 | 12 | # Xcode 13 | # 14 | build/ 15 | *.pbxuser 16 | !default.pbxuser 17 | *.mode1v3 18 | !default.mode1v3 19 | *.mode2v3 20 | !default.mode2v3 21 | *.perspectivev3 22 | !default.perspectivev3 23 | xcuserdata 24 | *.xccheckout 25 | *.moved-aside 26 | DerivedData 27 | *.hmap 28 | *.ipa 29 | *.xcuserstate 30 | project.xcworkspace 31 | 32 | # Android/IJ 33 | # 34 | .idea 35 | .gradle 36 | local.properties 37 | android.iml 38 | 39 | # Cocoapods 40 | # 41 | example/ios/Pods 42 | 43 | # node.js 44 | # 45 | node_modules/ 46 | npm-debug.log 47 | yarn-debug.log 48 | yarn-error.log 49 | 50 | # BUCK 51 | buck-out/ 52 | \.buckd/ 53 | android/app/libs 54 | android/keystores/debug.keystore 55 | 56 | # Expo 57 | .expo/* 58 | 59 | # generated by bob 60 | lib/ 61 | 62 | .env 63 | google-services.json 64 | 65 | ## Bundler environment 66 | /.bundle/ 67 | /vendor/bundle 68 | /lib/bundler/man/ 69 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 16 2 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 22.14.0 2 | -------------------------------------------------------------------------------- /.refactorer/config.md: -------------------------------------------------------------------------------- 1 | ## Checks 2 | 3 | ### yarn lint 4 | 5 | `yarn lint` failed with the following output: 6 | 7 | 8 | {output} 9 | 10 | 11 | Your task is to understand and fix all linting errors. Do run `yarn lint` again when you're done to be sure that everything is fixed. 12 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.3.4 2 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | # Override Yarn command so we can automatically setup the repo on running `yarn` 2 | 3 | yarn-path "scripts/bootstrap.js" 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby '3.3.4' 5 | 6 | gem 'activesupport', '~> 7.2' 7 | gem 'cocoapods', '~> 1.16' 8 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.7) 5 | base64 6 | nkf 7 | rexml 8 | activesupport (7.2.2.1) 9 | base64 10 | benchmark (>= 0.3) 11 | bigdecimal 12 | concurrent-ruby (~> 1.0, >= 1.3.1) 13 | connection_pool (>= 2.2.5) 14 | drb 15 | i18n (>= 1.6, < 2) 16 | logger (>= 1.4.2) 17 | minitest (>= 5.1) 18 | securerandom (>= 0.3) 19 | tzinfo (~> 2.0, >= 2.0.5) 20 | addressable (2.8.7) 21 | public_suffix (>= 2.0.2, < 7.0) 22 | algoliasearch (1.27.5) 23 | httpclient (~> 2.8, >= 2.8.3) 24 | json (>= 1.5.1) 25 | atomos (0.1.3) 26 | base64 (0.2.0) 27 | benchmark (0.4.0) 28 | bigdecimal (3.1.9) 29 | claide (1.1.0) 30 | cocoapods (1.16.2) 31 | addressable (~> 2.8) 32 | claide (>= 1.0.2, < 2.0) 33 | cocoapods-core (= 1.16.2) 34 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 35 | cocoapods-downloader (>= 2.1, < 3.0) 36 | cocoapods-plugins (>= 1.0.0, < 2.0) 37 | cocoapods-search (>= 1.0.0, < 2.0) 38 | cocoapods-trunk (>= 1.6.0, < 2.0) 39 | cocoapods-try (>= 1.1.0, < 2.0) 40 | colored2 (~> 3.1) 41 | escape (~> 0.0.4) 42 | fourflusher (>= 2.3.0, < 3.0) 43 | gh_inspector (~> 1.0) 44 | molinillo (~> 0.8.0) 45 | nap (~> 1.0) 46 | ruby-macho (>= 2.3.0, < 3.0) 47 | xcodeproj (>= 1.27.0, < 2.0) 48 | cocoapods-core (1.16.2) 49 | activesupport (>= 5.0, < 8) 50 | addressable (~> 2.8) 51 | algoliasearch (~> 1.0) 52 | concurrent-ruby (~> 1.1) 53 | fuzzy_match (~> 2.0.4) 54 | nap (~> 1.0) 55 | netrc (~> 0.11) 56 | public_suffix (~> 4.0) 57 | typhoeus (~> 1.0) 58 | cocoapods-deintegrate (1.0.5) 59 | cocoapods-downloader (2.1) 60 | cocoapods-plugins (1.0.0) 61 | nap 62 | cocoapods-search (1.0.1) 63 | cocoapods-trunk (1.6.0) 64 | nap (>= 0.8, < 2.0) 65 | netrc (~> 0.11) 66 | cocoapods-try (1.2.0) 67 | colored2 (3.1.2) 68 | concurrent-ruby (1.3.5) 69 | connection_pool (2.5.0) 70 | drb (2.2.1) 71 | escape (0.0.4) 72 | ethon (0.16.0) 73 | ffi (>= 1.15.0) 74 | ffi (1.17.1) 75 | fourflusher (2.3.1) 76 | fuzzy_match (2.0.4) 77 | gh_inspector (1.1.3) 78 | httpclient (2.8.3) 79 | i18n (1.14.7) 80 | concurrent-ruby (~> 1.0) 81 | json (2.10.2) 82 | logger (1.6.6) 83 | minitest (5.25.4) 84 | molinillo (0.8.0) 85 | nanaimo (0.4.0) 86 | nap (1.1.0) 87 | netrc (0.11.0) 88 | nkf (0.2.0) 89 | public_suffix (4.0.7) 90 | rexml (3.4.1) 91 | ruby-macho (2.5.1) 92 | securerandom (0.4.1) 93 | typhoeus (1.4.1) 94 | ethon (>= 0.9.0) 95 | tzinfo (2.0.6) 96 | concurrent-ruby (~> 1.0) 97 | xcodeproj (1.27.0) 98 | CFPropertyList (>= 2.3.3, < 4.0) 99 | atomos (~> 0.1.3) 100 | claide (>= 1.0.2, < 2.0) 101 | colored2 (~> 3.1) 102 | nanaimo (~> 0.4.0) 103 | rexml (>= 3.3.6, < 4.0) 104 | 105 | PLATFORMS 106 | ruby 107 | 108 | DEPENDENCIES 109 | activesupport (~> 7.2) 110 | cocoapods (~> 1.16) 111 | 112 | RUBY VERSION 113 | ruby 3.3.4p94 114 | 115 | BUNDLED WITH 116 | 2.1.4 117 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2011- Intercom, Inc. (https://www.intercom.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /REPO_OWNER: -------------------------------------------------------------------------------- 1 | team-messenger 2 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/rndiffapp/newarchitecture/MainApplicationReactNativeHost.java: -------------------------------------------------------------------------------- 1 | package com.rndiffapp.newarchitecture; 2 | 3 | import android.app.Application; 4 | import androidx.annotation.NonNull; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactInstanceManager; 7 | import com.facebook.react.ReactNativeHost; 8 | import com.facebook.react.ReactPackage; 9 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate; 10 | import com.facebook.react.bridge.JSIModulePackage; 11 | import com.facebook.react.bridge.JSIModuleProvider; 12 | import com.facebook.react.bridge.JSIModuleSpec; 13 | import com.facebook.react.bridge.JSIModuleType; 14 | import com.facebook.react.bridge.JavaScriptContextHolder; 15 | import com.facebook.react.bridge.ReactApplicationContext; 16 | import com.facebook.react.bridge.UIManager; 17 | import com.facebook.react.fabric.ComponentFactory; 18 | import com.facebook.react.fabric.CoreComponentsRegistry; 19 | import com.facebook.react.fabric.FabricJSIModuleProvider; 20 | import com.facebook.react.fabric.ReactNativeConfig; 21 | import com.facebook.react.uimanager.ViewManagerRegistry; 22 | import com.rndiffapp.BuildConfig; 23 | import com.rndiffapp.newarchitecture.components.MainComponentsRegistry; 24 | import com.rndiffapp.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate; 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | 28 | /** 29 | * A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both 30 | * TurboModule delegates and the Fabric Renderer. 31 | * 32 | *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the 33 | * `newArchEnabled` property). Is ignored otherwise. 34 | */ 35 | public class MainApplicationReactNativeHost extends ReactNativeHost { 36 | public MainApplicationReactNativeHost(Application application) { 37 | super(application); 38 | } 39 | 40 | @Override 41 | public boolean getUseDeveloperSupport() { 42 | return BuildConfig.DEBUG; 43 | } 44 | 45 | @Override 46 | protected List getPackages() { 47 | List packages = new PackageList(this).getPackages(); 48 | // Packages that cannot be autolinked yet can be added manually here, for example: 49 | // packages.add(new MyReactNativePackage()); 50 | // TurboModules must also be loaded here providing a valid TurboReactPackage implementation: 51 | // packages.add(new TurboReactPackage() { ... }); 52 | // If you have custom Fabric Components, their ViewManagers should also be loaded here 53 | // inside a ReactPackage. 54 | return packages; 55 | } 56 | 57 | @Override 58 | protected String getJSMainModuleName() { 59 | return "index"; 60 | } 61 | 62 | @NonNull 63 | @Override 64 | protected ReactPackageTurboModuleManagerDelegate.Builder 65 | getReactPackageTurboModuleManagerDelegateBuilder() { 66 | // Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary 67 | // for the new architecture and to use TurboModules correctly. 68 | return new MainApplicationTurboModuleManagerDelegate.Builder(); 69 | } 70 | 71 | @Override 72 | protected JSIModulePackage getJSIModulePackage() { 73 | return new JSIModulePackage() { 74 | @Override 75 | public List getJSIModules( 76 | final ReactApplicationContext reactApplicationContext, 77 | final JavaScriptContextHolder jsContext) { 78 | final List specs = new ArrayList<>(); 79 | 80 | // Here we provide a new JSIModuleSpec that will be responsible of providing the 81 | // custom Fabric Components. 82 | specs.add( 83 | new JSIModuleSpec() { 84 | @Override 85 | public JSIModuleType getJSIModuleType() { 86 | return JSIModuleType.UIManager; 87 | } 88 | 89 | @Override 90 | public JSIModuleProvider getJSIModuleProvider() { 91 | final ComponentFactory componentFactory = new ComponentFactory(); 92 | CoreComponentsRegistry.register(componentFactory); 93 | 94 | // Here we register a Components Registry. 95 | // The one that is generated with the template contains no components 96 | // and just provides you the one from React Native core. 97 | MainComponentsRegistry.register(componentFactory); 98 | 99 | final ReactInstanceManager reactInstanceManager = getReactInstanceManager(); 100 | 101 | ViewManagerRegistry viewManagerRegistry = 102 | new ViewManagerRegistry( 103 | reactInstanceManager.getOrCreateViewManagers(reactApplicationContext)); 104 | 105 | return new FabricJSIModuleProvider( 106 | reactApplicationContext, 107 | componentFactory, 108 | ReactNativeConfig.DEFAULT_CONFIG, 109 | viewManagerRegistry); 110 | } 111 | }); 112 | return specs; 113 | } 114 | }; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/rndiffapp/newarchitecture/components/MainComponentsRegistry.java: -------------------------------------------------------------------------------- 1 | package com.rndiffapp.newarchitecture.components; 2 | 3 | import com.facebook.jni.HybridData; 4 | import com.facebook.proguard.annotations.DoNotStrip; 5 | import com.facebook.react.fabric.ComponentFactory; 6 | import com.facebook.soloader.SoLoader; 7 | 8 | /** 9 | * Class responsible to load the custom Fabric Components. This class has native methods and needs a 10 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ 11 | * folder for you). 12 | * 13 | *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the 14 | * `newArchEnabled` property). Is ignored otherwise. 15 | */ 16 | @DoNotStrip 17 | public class MainComponentsRegistry { 18 | static { 19 | SoLoader.loadLibrary("fabricjni"); 20 | } 21 | 22 | @DoNotStrip private final HybridData mHybridData; 23 | 24 | @DoNotStrip 25 | private native HybridData initHybrid(ComponentFactory componentFactory); 26 | 27 | @DoNotStrip 28 | private MainComponentsRegistry(ComponentFactory componentFactory) { 29 | mHybridData = initHybrid(componentFactory); 30 | } 31 | 32 | @DoNotStrip 33 | public static MainComponentsRegistry register(ComponentFactory componentFactory) { 34 | return new MainComponentsRegistry(componentFactory); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/rndiffapp/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java: -------------------------------------------------------------------------------- 1 | package com.rndiffapp.newarchitecture.modules; 2 | 3 | import com.facebook.jni.HybridData; 4 | import com.facebook.react.ReactPackage; 5 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.soloader.SoLoader; 8 | import java.util.List; 9 | 10 | /** 11 | * Class responsible to load the TurboModules. This class has native methods and needs a 12 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ 13 | * folder for you). 14 | * 15 | *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the 16 | * `newArchEnabled` property). Is ignored otherwise. 17 | */ 18 | public class MainApplicationTurboModuleManagerDelegate 19 | extends ReactPackageTurboModuleManagerDelegate { 20 | 21 | private static volatile boolean sIsSoLibraryLoaded; 22 | 23 | protected MainApplicationTurboModuleManagerDelegate( 24 | ReactApplicationContext reactApplicationContext, List packages) { 25 | super(reactApplicationContext, packages); 26 | } 27 | 28 | protected native HybridData initHybrid(); 29 | 30 | native boolean canCreateTurboModule(String moduleName); 31 | 32 | public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder { 33 | protected MainApplicationTurboModuleManagerDelegate build( 34 | ReactApplicationContext context, List packages) { 35 | return new MainApplicationTurboModuleManagerDelegate(context, packages); 36 | } 37 | } 38 | 39 | @Override 40 | protected synchronized void maybeLoadOtherSoLibraries() { 41 | if (!sIsSoLibraryLoaded) { 42 | // If you change the name of your application .so file in the Android.mk file, 43 | // make sure you update the name here as well. 44 | SoLoader.loadLibrary("rndiffapp_appmodules"); 45 | sIsSoLibraryLoaded = true; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /android/app/src/main/jni/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | # Define the library name here. 4 | project(rndiffapp_appmodules) 5 | 6 | # This file includes all the necessary to let you build your application with the New Architecture. 7 | include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake) 8 | -------------------------------------------------------------------------------- /android/app/src/main/jni/MainApplicationModuleProvider.cpp: -------------------------------------------------------------------------------- 1 | #include "MainApplicationModuleProvider.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace facebook { 7 | namespace react { 8 | 9 | std::shared_ptr MainApplicationModuleProvider( 10 | const std::string &moduleName, 11 | const JavaTurboModule::InitParams ¶ms) { 12 | // Here you can provide your own module provider for TurboModules coming from 13 | // either your application or from external libraries. The approach to follow 14 | // is similar to the following (for a library called `samplelibrary`: 15 | // 16 | // auto module = samplelibrary_ModuleProvider(moduleName, params); 17 | // if (module != nullptr) { 18 | // return module; 19 | // } 20 | // return rncore_ModuleProvider(moduleName, params); 21 | 22 | // Module providers autolinked by RN CLI 23 | auto rncli_module = rncli_ModuleProvider(moduleName, params); 24 | if (rncli_module != nullptr) { 25 | return rncli_module; 26 | } 27 | 28 | return rncore_ModuleProvider(moduleName, params); 29 | } 30 | 31 | } // namespace react 32 | } // namespace facebook 33 | -------------------------------------------------------------------------------- /android/app/src/main/jni/MainApplicationModuleProvider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace facebook { 9 | namespace react { 10 | 11 | std::shared_ptr MainApplicationModuleProvider( 12 | const std::string &moduleName, 13 | const JavaTurboModule::InitParams ¶ms); 14 | 15 | } // namespace react 16 | } // namespace facebook 17 | -------------------------------------------------------------------------------- /android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp: -------------------------------------------------------------------------------- 1 | #include "MainApplicationTurboModuleManagerDelegate.h" 2 | #include "MainApplicationModuleProvider.h" 3 | 4 | namespace facebook { 5 | namespace react { 6 | 7 | jni::local_ref 8 | MainApplicationTurboModuleManagerDelegate::initHybrid( 9 | jni::alias_ref) { 10 | return makeCxxInstance(); 11 | } 12 | 13 | void MainApplicationTurboModuleManagerDelegate::registerNatives() { 14 | registerHybrid({ 15 | makeNativeMethod( 16 | "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid), 17 | makeNativeMethod( 18 | "canCreateTurboModule", 19 | MainApplicationTurboModuleManagerDelegate::canCreateTurboModule), 20 | }); 21 | } 22 | 23 | std::shared_ptr 24 | MainApplicationTurboModuleManagerDelegate::getTurboModule( 25 | const std::string &name, 26 | const std::shared_ptr &jsInvoker) { 27 | // Not implemented yet: provide pure-C++ NativeModules here. 28 | return nullptr; 29 | } 30 | 31 | std::shared_ptr 32 | MainApplicationTurboModuleManagerDelegate::getTurboModule( 33 | const std::string &name, 34 | const JavaTurboModule::InitParams ¶ms) { 35 | return MainApplicationModuleProvider(name, params); 36 | } 37 | 38 | bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule( 39 | const std::string &name) { 40 | return getTurboModule(name, nullptr) != nullptr || 41 | getTurboModule(name, {.moduleName = name}) != nullptr; 42 | } 43 | 44 | } // namespace react 45 | } // namespace facebook 46 | -------------------------------------------------------------------------------- /android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | namespace facebook { 8 | namespace react { 9 | 10 | class MainApplicationTurboModuleManagerDelegate 11 | : public jni::HybridClass< 12 | MainApplicationTurboModuleManagerDelegate, 13 | TurboModuleManagerDelegate> { 14 | public: 15 | // Adapt it to the package you used for your Java class. 16 | static constexpr auto kJavaDescriptor = 17 | "Lcom/rndiffapp/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;"; 18 | 19 | static jni::local_ref initHybrid(jni::alias_ref); 20 | 21 | static void registerNatives(); 22 | 23 | std::shared_ptr getTurboModule( 24 | const std::string &name, 25 | const std::shared_ptr &jsInvoker) override; 26 | std::shared_ptr getTurboModule( 27 | const std::string &name, 28 | const JavaTurboModule::InitParams ¶ms) override; 29 | 30 | /** 31 | * Test-only method. Allows user to verify whether a TurboModule can be 32 | * created by instances of this class. 33 | */ 34 | bool canCreateTurboModule(const std::string &name); 35 | }; 36 | 37 | } // namespace react 38 | } // namespace facebook 39 | -------------------------------------------------------------------------------- /android/app/src/main/jni/MainComponentsRegistry.cpp: -------------------------------------------------------------------------------- 1 | #include "MainComponentsRegistry.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace facebook { 10 | namespace react { 11 | 12 | MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {} 13 | 14 | std::shared_ptr 15 | MainComponentsRegistry::sharedProviderRegistry() { 16 | auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry(); 17 | 18 | // Autolinked providers registered by RN CLI 19 | rncli_registerProviders(providerRegistry); 20 | 21 | // Custom Fabric Components go here. You can register custom 22 | // components coming from your App or from 3rd party libraries here. 23 | // 24 | // providerRegistry->add(concreteComponentDescriptorProvider< 25 | // AocViewerComponentDescriptor>()); 26 | return providerRegistry; 27 | } 28 | 29 | jni::local_ref 30 | MainComponentsRegistry::initHybrid( 31 | jni::alias_ref, 32 | ComponentFactory *delegate) { 33 | auto instance = makeCxxInstance(delegate); 34 | 35 | auto buildRegistryFunction = 36 | [](EventDispatcher::Weak const &eventDispatcher, 37 | ContextContainer::Shared const &contextContainer) 38 | -> ComponentDescriptorRegistry::Shared { 39 | auto registry = MainComponentsRegistry::sharedProviderRegistry() 40 | ->createComponentDescriptorRegistry( 41 | {eventDispatcher, contextContainer}); 42 | 43 | auto mutableRegistry = 44 | std::const_pointer_cast(registry); 45 | 46 | mutableRegistry->setFallbackComponentDescriptor( 47 | std::make_shared( 48 | ComponentDescriptorParameters{ 49 | eventDispatcher, contextContainer, nullptr})); 50 | 51 | return registry; 52 | }; 53 | 54 | delegate->buildRegistryFunction = buildRegistryFunction; 55 | return instance; 56 | } 57 | 58 | void MainComponentsRegistry::registerNatives() { 59 | registerHybrid({ 60 | makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid), 61 | }); 62 | } 63 | 64 | } // namespace react 65 | } // namespace facebook 66 | -------------------------------------------------------------------------------- /android/app/src/main/jni/MainComponentsRegistry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace facebook { 9 | namespace react { 10 | 11 | class MainComponentsRegistry 12 | : public facebook::jni::HybridClass { 13 | public: 14 | // Adapt it to the package you used for your Java class. 15 | constexpr static auto kJavaDescriptor = 16 | "Lcom/rndiffapp/newarchitecture/components/MainComponentsRegistry;"; 17 | 18 | static void registerNatives(); 19 | 20 | MainComponentsRegistry(ComponentFactory *delegate); 21 | 22 | private: 23 | static std::shared_ptr 24 | sharedProviderRegistry(); 25 | 26 | static jni::local_ref initHybrid( 27 | jni::alias_ref, 28 | ComponentFactory *delegate); 29 | }; 30 | 31 | } // namespace react 32 | } // namespace facebook 33 | -------------------------------------------------------------------------------- /android/app/src/main/jni/OnLoad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "MainApplicationTurboModuleManagerDelegate.h" 3 | #include "MainComponentsRegistry.h" 4 | 5 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { 6 | return facebook::jni::initialize(vm, [] { 7 | facebook::react::MainApplicationTurboModuleManagerDelegate:: 8 | registerNatives(); 9 | facebook::react::MainComponentsRegistry::registerNatives(); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 21 | 22 | 23 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | def packageJsonFile = file('../package.json') 2 | def packageJson = new groovy.json.JsonSlurper().parseText(packageJsonFile.text) 3 | def packageVersion = '"' + packageJson.version + '"' 4 | 5 | 6 | buildscript { 7 | ext { 8 | buildToolsVersion = "35.0.0" 9 | minSdkVersion = 23 10 | compileSdkVersion = 35 11 | targetSdkVersion = 35 12 | ndkVersion = "26.1.10909125" 13 | kotlinVersion = "1.9.22" 14 | } 15 | if (project == rootProject) { 16 | repositories { 17 | google() 18 | mavenCentral() 19 | } 20 | 21 | dependencies { 22 | classpath("com.android.tools.build:gradle") 23 | classpath("com.facebook.react:react-native-gradle-plugin") 24 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 25 | } 26 | } 27 | } 28 | 29 | apply plugin: 'com.android.library' 30 | 31 | def safeExtGet(prop, fallback) { 32 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 33 | } 34 | 35 | android { 36 | namespace 'com.intercom.reactnative' 37 | compileSdk rootProject.ext.compileSdkVersion 38 | buildToolsVersion rootProject.ext.buildToolsVersion 39 | 40 | defaultConfig { 41 | minSdkVersion rootProject.ext.minSdkVersion 42 | targetSdkVersion rootProject.ext.targetSdkVersion 43 | versionCode 1 44 | versionName "1.0" 45 | buildConfigField 'String', 'INTERCOM_VERSION_NAME', packageVersion 46 | } 47 | 48 | buildTypes { 49 | release { 50 | minifyEnabled false 51 | } 52 | } 53 | lintOptions { 54 | disable 'GradleCompatible' 55 | } 56 | } 57 | 58 | repositories { 59 | mavenCentral() 60 | mavenLocal() 61 | maven { 62 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 63 | url("$rootDir/../node_modules/react-native/android") 64 | } 65 | google() 66 | } 67 | 68 | dependencies { 69 | //noinspection GradleDynamicVersion 70 | implementation "com.facebook.react:react-native:+" // From node_modules 71 | implementation "com.google.firebase:firebase-messaging:${safeExtGet('firebaseMessagingVersion', '20.2.+')}" 72 | implementation 'io.intercom.android:intercom-sdk:15.16.+' 73 | } 74 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto execute 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto execute 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :execute 65 | @rem Setup the command line 66 | 67 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 68 | 69 | 70 | @rem Execute Gradle 71 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 72 | 73 | :end 74 | @rem End local scope for the variables with windows NT shell 75 | if "%ERRORLEVEL%"=="0" goto mainEnd 76 | 77 | :fail 78 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 79 | rem the _cmd.exe /c_ return code! 80 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 81 | exit /b 1 82 | 83 | :mainEnd 84 | if "%OS%"=="Windows_NT" endlocal 85 | 86 | :omega 87 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/java/com/intercom/reactnative/IntercomErrorCodes.java: -------------------------------------------------------------------------------- 1 | package com.intercom.reactnative; 2 | 3 | public class IntercomErrorCodes { 4 | public static final String UNIDENTIFIED_REGISTRATION = "101"; 5 | public static final String IDENTIFIED_REGISTRATION = "102"; 6 | public static final String SET_USER_HASH = "103"; 7 | public static final String UPDATE_USER_HASH = "104"; 8 | public static final String LOG_EVENT_HASH = "105"; 9 | public static final String LOGOUT = "106"; 10 | public static final String SET_LOG_LEVEL = "107"; 11 | public static final String GET_UNREAD_CONVERSATION = "108"; 12 | public static final String DISPLAY_MESSENGER = "201"; 13 | public static final String DISPLAY_MESSENGER_COMPOSER = "202"; 14 | public static final String DISPLAY_CONTENT = "203"; 15 | public static final String SET_IN_APP_MESSAGE_VISIBILITY = "205"; 16 | public static final String HIDE_INTERCOM = "206"; 17 | public static final String SET_LAUNCHER_VISIBILITY = "208"; 18 | public static final String SET_BOTTOM_PADDING = "209"; 19 | public static final String HANDLE_PUSH_MESSAGE = "301"; 20 | public static final String SEND_TOKEN_TO_INTERCOM = "302"; 21 | public static final String FETCH_HELP_CENTER_COLLECTIONS = "901"; 22 | public static final String FETCH_HELP_CENTER_COLLECTION = "902"; 23 | public static final String SEARCH_HELP_CENTER = "903"; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /android/src/main/java/com/intercom/reactnative/IntercomEventEmitter.java: -------------------------------------------------------------------------------- 1 | package com.intercom.reactnative; 2 | 3 | import android.util.Log; 4 | 5 | import com.facebook.react.bridge.Arguments; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 8 | import com.facebook.react.bridge.ReactMethod; 9 | import com.facebook.react.bridge.WritableMap; 10 | import com.facebook.react.module.annotations.ReactModule; 11 | import com.facebook.react.modules.core.DeviceEventManagerModule; 12 | 13 | import javax.annotation.Nullable; 14 | 15 | import java.util.Map; 16 | import java.util.HashMap; 17 | 18 | import io.intercom.android.sdk.Intercom; 19 | import io.intercom.android.sdk.UnreadConversationCountListener; 20 | 21 | @ReactModule(name = IntercomEventEmitter.NAME) 22 | public class IntercomEventEmitter extends ReactContextBaseJavaModule { 23 | 24 | public static final String NAME = "IntercomEventEmitter"; 25 | private static final String UNREAD_COUNT_CHANGE_NOTIFICATION = "IntercomUnreadConversationCountDidChangeNotification"; 26 | private int activeListenersCount = 0; 27 | private final UnreadConversationCountListener unreadConversationCountListener = new UnreadConversationCountListener() { 28 | @Override 29 | public void onCountUpdate(int conversationCount) { 30 | updateUnreadCount(); 31 | } 32 | }; 33 | 34 | public IntercomEventEmitter(ReactApplicationContext reactContext) { 35 | super(reactContext); 36 | } 37 | 38 | @ReactMethod 39 | public void addListener(String eventName) { 40 | // Keep: Required for RN built in Event Emitter Calls. 41 | } 42 | 43 | @ReactMethod 44 | public void removeListeners(Integer count) { 45 | // Keep: Required for RN built in Event Emitter Calls. 46 | } 47 | 48 | @ReactMethod 49 | public void startEventListener() { 50 | try { 51 | if (activeListenersCount == 0) { 52 | Intercom.client().addUnreadConversationCountListener(unreadConversationCountListener); 53 | } 54 | activeListenersCount += 1; 55 | } catch (Exception e) { 56 | Log.e(NAME, "startEventListener error:"); 57 | Log.e(NAME, e.toString()); 58 | } 59 | } 60 | 61 | @ReactMethod 62 | public void removeEventListener() { 63 | try { 64 | activeListenersCount -= 1; 65 | if (activeListenersCount == 0) { 66 | Intercom.client().removeUnreadConversationCountListener(unreadConversationCountListener); 67 | } 68 | } catch (Exception e) { 69 | Log.e(NAME, "removeEventListener error:"); 70 | Log.e(NAME, e.toString()); 71 | } 72 | } 73 | 74 | @Override 75 | public String getName() { 76 | return NAME; 77 | } 78 | 79 | @Override 80 | public Map getConstants() { 81 | final Map constants = new HashMap<>(); 82 | constants.put("UNREAD_COUNT_CHANGE_NOTIFICATION", UNREAD_COUNT_CHANGE_NOTIFICATION); 83 | return constants; 84 | } 85 | 86 | private void updateUnreadCount() { 87 | try { 88 | WritableMap params = Arguments.createMap(); 89 | params.putInt("count", Intercom.client().getUnreadConversationCount()); 90 | Log.d(NAME, "handleUpdateUnreadCount"); 91 | sendEvent(UNREAD_COUNT_CHANGE_NOTIFICATION, params); 92 | } catch (Exception e) { 93 | Log.e(NAME, "client called before Intercom initialization"); 94 | } 95 | } 96 | 97 | private void sendEvent(String eventName, @Nullable WritableMap params) { 98 | if (getReactApplicationContext().hasActiveCatalystInstance()) { 99 | try { 100 | getReactApplicationContext() 101 | .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) 102 | .emit(eventName, params); 103 | } catch (Exception e) { 104 | Log.e(NAME, "sendEvent called before bundle loaded"); 105 | } 106 | } 107 | } 108 | 109 | 110 | } 111 | -------------------------------------------------------------------------------- /android/src/main/java/com/intercom/reactnative/IntercomHelpCenterHelpers.java: -------------------------------------------------------------------------------- 1 | package com.intercom.reactnative; 2 | 3 | 4 | import com.facebook.react.bridge.Arguments; 5 | import com.facebook.react.bridge.ReadableArray; 6 | import com.facebook.react.bridge.ReadableMap; 7 | import com.facebook.react.bridge.WritableArray; 8 | import com.facebook.react.bridge.WritableMap; 9 | 10 | 11 | import java.util.List; 12 | 13 | import io.intercom.android.sdk.helpcenter.api.HelpCenterArticleSearchResult; 14 | import io.intercom.android.sdk.helpcenter.collections.HelpCenterCollection; 15 | import io.intercom.android.sdk.helpcenter.sections.HelpCenterArticle; 16 | import io.intercom.android.sdk.helpcenter.sections.HelpCenterCollectionContent; 17 | 18 | public class IntercomHelpCenterHelpers { 19 | 20 | public static WritableArray parseArticlesToReadableArray(List itemArticles) { 21 | WritableArray articles = Arguments.createArray(); 22 | 23 | HelpCenterArticle[] articlesArray = new HelpCenterArticle[itemArticles.size()]; 24 | articlesArray = itemArticles.toArray(articlesArray); 25 | 26 | for (HelpCenterArticle article : articlesArray) { 27 | WritableMap item = Arguments.createMap(); 28 | item.putString("id", article.getArticleId()); 29 | item.putString("title", article.getTitle()); 30 | articles.pushMap(item); 31 | } 32 | return articles; 33 | } 34 | 35 | public static WritableArray parseHelpCenterArticleSearchToReadableArray(List helpCenterArticleSearchResultList) { 36 | WritableArray articles = Arguments.createArray(); 37 | 38 | HelpCenterArticleSearchResult[] articlesArray = new HelpCenterArticleSearchResult[helpCenterArticleSearchResultList.size()]; 39 | articlesArray = helpCenterArticleSearchResultList.toArray(articlesArray); 40 | 41 | for (HelpCenterArticleSearchResult article : articlesArray) { 42 | WritableMap item = Arguments.createMap(); 43 | item.putString("id", article.getArticleId()); 44 | item.putString("title", article.getTitle()); 45 | item.putString("matchingSnippet", article.getMatchingSnippet()); 46 | item.putString("summary", article.getSummary()); 47 | articles.pushMap(item); 48 | } 49 | return articles; 50 | } 51 | 52 | public static WritableMap parseHelpCenterCollectionsContentToReadableMap(HelpCenterCollectionContent helpCenterCollectionContent) { 53 | WritableMap helpCenterCollection = Arguments.createMap(); 54 | helpCenterCollection.putString("id", helpCenterCollectionContent.getCollectionId()); 55 | helpCenterCollection.putString("title", helpCenterCollectionContent.getTitle()); 56 | helpCenterCollection.putString("summary", helpCenterCollectionContent.getSummary()); 57 | 58 | WritableArray articles = parseArticlesToReadableArray(helpCenterCollectionContent.getHelpCenterArticles()); 59 | helpCenterCollection.putArray("articles", articles); 60 | 61 | WritableArray collections = parseHelpCenterCollectionsToReadableArray(helpCenterCollectionContent.getSubCollections()); 62 | helpCenterCollection.putArray("collections", collections); 63 | 64 | 65 | return helpCenterCollection; 66 | } 67 | 68 | public static WritableArray parseHelpCenterCollectionsToReadableArray(List helpCenterCollections) { 69 | HelpCenterCollection[] collectionsArray = new HelpCenterCollection[helpCenterCollections.size()]; 70 | collectionsArray = helpCenterCollections.toArray(collectionsArray); 71 | WritableArray collections = Arguments.createArray(); 72 | for (HelpCenterCollection helpCenterCollection : collectionsArray) { 73 | WritableMap item = Arguments.createMap(); 74 | item.putString("id", helpCenterCollection.getId()); 75 | item.putString("title", helpCenterCollection.getTitle()); 76 | item.putString("summary", helpCenterCollection.getSummary()); 77 | collections.pushMap(item); 78 | } 79 | return collections; 80 | } 81 | 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /android/src/main/java/com/intercom/reactnative/IntercomPackage.java: -------------------------------------------------------------------------------- 1 | package com.intercom.reactnative; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import com.facebook.react.ReactPackage; 6 | import com.facebook.react.bridge.NativeModule; 7 | import com.facebook.react.bridge.ReactApplicationContext; 8 | import com.facebook.react.uimanager.ViewManager; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | public class IntercomPackage implements ReactPackage { 15 | @NonNull 16 | @Override 17 | public List createNativeModules(@NonNull ReactApplicationContext reactContext) { 18 | List modules = new ArrayList<>(); 19 | modules.add(new IntercomModule(reactContext)); 20 | modules.add(new IntercomEventEmitter(reactContext)); 21 | return modules; 22 | } 23 | 24 | @NonNull 25 | @Override 26 | public List createViewManagers(@NonNull ReactApplicationContext reactContext) { 27 | return Collections.emptyList(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /android/src/main/java/com/intercom/reactnative/RNIntercomPushBroadcastReceiver.java: -------------------------------------------------------------------------------- 1 | package com.intercom.reactnative; 2 | 3 | import io.intercom.android.sdk.push.IntercomPushBroadcastReceiver; 4 | 5 | public class RNIntercomPushBroadcastReceiver extends IntercomPushBroadcastReceiver { 6 | } 7 | -------------------------------------------------------------------------------- /android/src/main/java/io/intercom/android/sdk/api/ReactNativeHeaderInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.intercom.android.sdk.api; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | public class ReactNativeHeaderInterceptor { 7 | public static void setReactNativeVersion(Context context, String rnVersion) { 8 | HeaderInterceptor.setReactNativeVersion(context, rnVersion); 9 | Log.d("ReactNativeHeader", "Registered RN Header"); 10 | Log.d("ReactNativeHeader", rnVersion); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app.plugin.js: -------------------------------------------------------------------------------- 1 | const packageJson = require('./package.json'); 2 | 3 | const pkg = { 4 | // Prevent this plugin from being run more than once. 5 | // This pattern enables users to safely migrate off of this 6 | // out-of-tree `@config-plugins/intercom-react-native` to a future 7 | // upstream plugin in `intercom-react-native` 8 | name: packageJson.name, 9 | // Indicates that this plugin is dangerously linked to a module, 10 | // and might not work with the latest version of that module. 11 | version: packageJson.version, 12 | }; 13 | 14 | const plugin = require('./lib/commonjs/expo-plugins'); 15 | 16 | module.exports = plugin.default(pkg); 17 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/IOS-MANUAL-LINKING.md: -------------------------------------------------------------------------------- 1 | # Intercom IOS Manual linking 2 | 3 | ## More info about [Manual Linking](https://reactnative.dev/docs/linking-libraries-ios) 4 | 5 | - In project root make `react-native link` command 6 | - In Xcode open `YourApp.xcworkspace`, if there is no file with extension `xcworkspace` open `YourApp.xcodeproj` 7 | - [Download intercom for iOS and extract the zip](https://github.com/intercom/intercom-ios/archive/master.zip) 8 | - Drag Intercom.xcframework into your project. Make sure **"Copy items if needed"** is selected and click Finish. 9 | 10 | ![Xcode linking](https://files.readme.io/51cf138-xcframework_drag.png) 11 | 12 | ![Xcode popup](https://files.readme.io/031bc35-copy_items.png) 13 | 14 | ___ 15 | 16 | - 🎉 Done 🎉 Intercom SDK is linked 17 | -------------------------------------------------------------------------------- /docs/scheme-setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/docs/scheme-setup.png -------------------------------------------------------------------------------- /docs/xcode-linking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/docs/xcode-linking.png -------------------------------------------------------------------------------- /docs/xcode-popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/docs/xcode-popup.png -------------------------------------------------------------------------------- /example/.env.example: -------------------------------------------------------------------------------- 1 | IOS_INTERCOM_APP_ID=$IOS_INTERCOM_APP_ID 2 | IOS_INTERCOM_KEY=$IOS_INTERCOM_KEY 3 | ANDROID_INTERCOM_APP_ID=$ANDROID_INTERCOM_APP_ID 4 | ANDROID_INTERCOM_KEY=$ANDROID_INTERCOM_KEY 5 | CAROUSEL_ID=$CAROUSEL_ID 6 | SURVEY_ID=$SURVEY_ID 7 | EVENT_NAME=$EVENT_NAME 8 | ARTICLE_ID=$ARTICLE_ID 9 | USER_NAME=$USER_NAME 10 | COLLECTION_ID=$COLLECTION_ID 11 | SEARCH_TERM=$SEARCH_TERM 12 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Welcome to @intercom/intercom-react-native example app 👋 2 | 3 | ## Installation 4 | 5 | To get started with the @intercom/intercom-react-native example app, please follow the instructions below: 6 | 7 | 1. Install XCode before you setup the app. 8 | 9 | 2. Setup the app using: 10 | ```sh 11 | ./script/setup 12 | ``` 13 | This command will install all the dependencies required to run the example app. 14 | 15 | 3. Generate a new .env file by running the following command in your terminal: 16 | ```sh 17 | sh scripts/generateEnv.sh 18 | ``` 19 | This command will create a .env file inside the example directory. 20 | Fill in the required App ID in the .env file. Other variables are optional. 21 | 22 | ## Before you run the app 23 | 24 | Please set up your React Native Development Environment for Android as described in the guide below (if you didn't do it before): 25 | 26 | [Android enviroment setup](https://reactnative.dev/docs/environment-setup?package-manager=yarn&guide=native&platform=android) 27 | 28 | ## Running the app 29 | 30 | To run the app on Android, execute the following command: 31 | 32 | ```sh 33 | yarn example android 34 | ``` 35 | 36 | To run the app on Android, execute the following command: 37 | 38 | ```sh 39 | yarn example ios 40 | ``` 41 | 42 | ## Troubleshooting 43 | 44 | 1. If you are facing issues related to pods, you can install them separately using: 45 | ```sh 46 | pod install 47 | ``` 48 | 49 | 2. For issues related to android, try opening and running the example app from the android studio. 50 | 51 | 3. For general iOS build errors, opening and running the example app from XCode also helps. 52 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | apply plugin: "org.jetbrains.kotlin.android" 3 | apply plugin: "com.facebook.react" 4 | apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" 5 | 6 | def taskRequests = getGradle().getStartParameter().getTaskRequests().toString().toLowerCase() 7 | def isFoss = taskRequests.contains("foss") 8 | 9 | 10 | /** 11 | * This is the configuration block to customize your React Native Android app. 12 | * By default you don't need to apply any configuration, just uncomment the lines you need. 13 | */ 14 | react { 15 | /* Folders */ 16 | // The root of your project, i.e. where "package.json" lives. Default is '..' 17 | // root = file("../") 18 | // The folder where the react-native NPM package is. Default is ../node_modules/react-native 19 | // reactNativeDir = file("../node_modules/react-native") 20 | // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen 21 | // codegenDir = file("../node_modules/@react-native/codegen") 22 | // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js 23 | // cliFile = file("../node_modules/react-native/cli.js") 24 | 25 | /* Variants */ 26 | // The list of variants to that are debuggable. For those we're going to 27 | // skip the bundling of the JS bundle and the assets. By default is just 'debug'. 28 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. 29 | // debuggableVariants = ["liteDebug", "prodDebug"] 30 | 31 | /* Bundling */ 32 | // A list containing the node command and its flags. Default is just 'node'. 33 | // nodeExecutableAndArgs = ["node"] 34 | // 35 | // The command to run when bundling. By default is 'bundle' 36 | // bundleCommand = "ram-bundle" 37 | // 38 | // The path to the CLI configuration file. Default is empty. 39 | // bundleConfig = file(../rn-cli.config.js) 40 | // 41 | // The name of the generated asset file containing your JS bundle 42 | // bundleAssetName = "MyApplication.android.bundle" 43 | // 44 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' 45 | entryFile = file("index.tsx") 46 | // 47 | // A list of extra flags to pass to the 'bundle' commands. 48 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle 49 | // extraPackagerArgs = [] 50 | 51 | /* Hermes Commands */ 52 | // The hermes compiler command to run. By default it is 'hermesc' 53 | // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" 54 | // 55 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" 56 | // hermesFlags = ["-O", "-output-source-map"] 57 | } 58 | 59 | /** 60 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode. 61 | */ 62 | def enableProguardInReleaseBuilds = false 63 | 64 | /** 65 | * The preferred build flavor of JavaScriptCore (JSC) 66 | * 67 | * For example, to use the international variant, you can use: 68 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 69 | * 70 | * The international variant includes ICU i18n library and necessary data 71 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 72 | * give correct results when using with locales other than en-US. Note that 73 | * this variant is about 6MiB larger per architecture than default. 74 | */ 75 | def jscFlavor = 'org.webkit:android-jsc:+' 76 | 77 | android { 78 | ndkVersion rootProject.ext.ndkVersion 79 | buildToolsVersion rootProject.ext.buildToolsVersion 80 | compileSdk rootProject.ext.compileSdkVersion 81 | 82 | namespace "com.example.intercomreactnative" 83 | defaultConfig { 84 | applicationId "com.example.intercomreactnative" 85 | minSdkVersion rootProject.ext.minSdkVersion 86 | targetSdkVersion rootProject.ext.targetSdkVersion 87 | versionCode 1 88 | versionName "1.0" 89 | resValue "string", "build_config_package", "com.example.intercomreactnative" 90 | } 91 | signingConfigs { 92 | debug { 93 | storeFile file('debug.keystore') 94 | storePassword 'android' 95 | keyAlias 'androiddebugkey' 96 | keyPassword 'android' 97 | } 98 | } 99 | buildTypes { 100 | debug { 101 | signingConfig signingConfigs.debug 102 | } 103 | release { 104 | // Caution! In production, you need to generate your own keystore file. 105 | // see https://reactnative.dev/docs/signed-apk-android. 106 | signingConfig signingConfigs.debug 107 | minifyEnabled enableProguardInReleaseBuilds 108 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 109 | } 110 | } 111 | } 112 | 113 | dependencies { 114 | // The version of react-native is set by the React Native Gradle Plugin 115 | implementation("com.facebook.react:react-android") 116 | //implementation("com.facebook.react:flipper-integration") 117 | 118 | 119 | implementation 'com.google.firebase:firebase-messaging:20.2.+' 120 | 121 | if (hermesEnabled.toBoolean()) { 122 | implementation("com.facebook.react:hermes-android") 123 | } else { 124 | implementation jscFlavor 125 | } 126 | 127 | implementation project(':intercomreactnative') 128 | } 129 | 130 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 131 | -------------------------------------------------------------------------------- /example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/android/app/debug.keystore -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -keep class host.exp.exponent.BuildConfig { *; } 12 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 14 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/intercomreactnative/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.intercomreactnative; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. This is used to schedule 9 | * rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "IntercomReactNativeExample"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/intercomreactnative/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.intercomreactnative; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import com.facebook.react.ReactNativeHost; 8 | import com.facebook.react.ReactPackage; 9 | import com.facebook.react.ReactInstanceManager; 10 | import com.facebook.soloader.SoLoader; 11 | import java.lang.reflect.InvocationTargetException; 12 | import java.util.List; 13 | 14 | import com.lugg.RNCConfig.RNCConfigPackage; 15 | 16 | import com.intercom.reactnative.IntercomModule; 17 | import com.intercom.reactnative.IntercomPackage; 18 | 19 | public class MainApplication extends Application implements ReactApplication { 20 | 21 | private final ReactNativeHost mReactNativeHost = 22 | new ReactNativeHost(this) { 23 | @Override 24 | public boolean getUseDeveloperSupport() { 25 | return BuildConfig.DEBUG; 26 | } 27 | 28 | @Override 29 | protected List getPackages() { 30 | @SuppressWarnings("UnnecessaryLocalVariable") 31 | List packages = new PackageList(this).getPackages(); 32 | // Packages that cannot be autolinked yet can be added manually here, for IntercomReactNativeExample: 33 | // packages.add(new MyReactNativePackage()); 34 | packages.add(new IntercomPackage()); 35 | return packages; 36 | } 37 | 38 | @Override 39 | protected String getJSMainModuleName() { 40 | return "index"; 41 | } 42 | }; 43 | 44 | @Override 45 | public ReactNativeHost getReactNativeHost() { 46 | return mReactNativeHost; 47 | } 48 | 49 | @Override 50 | public void onCreate() { 51 | super.onCreate(); 52 | SoLoader.init(this, /* native exopackage */ false); 53 | 54 | String appId = BuildConfig.ANDROID_INTERCOM_APP_ID; 55 | String key = BuildConfig.ANDROID_INTERCOM_KEY; 56 | 57 | IntercomModule.initialize(this, key, appId); 58 | 59 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); // Remove this line if you don't want Flipper enabled 60 | } 61 | 62 | /** 63 | * Loads Flipper in React Native templates. 64 | * 65 | * @param context 66 | */ 67 | private static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 68 | if (BuildConfig.DEBUG) { 69 | try { 70 | /* 71 | We use reflection here to pick up the class that initializes Flipper, 72 | since Flipper library is not available in release mode 73 | */ 74 | Class aClass = Class.forName("com.intercomreactnativeExample.ReactNativeFlipper"); 75 | aClass 76 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) 77 | .invoke(null, context, reactInstanceManager); 78 | } catch (ClassNotFoundException e) { 79 | e.printStackTrace(); 80 | } catch (NoSuchMethodException e) { 81 | e.printStackTrace(); 82 | } catch (IllegalAccessException e) { 83 | e.printStackTrace(); 84 | } catch (InvocationTargetException e) { 85 | e.printStackTrace(); 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | IntercomReactNative Example 3 | 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/android/app/src/play/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/play/java/com/example/intercomreactnative/MainNotificationService.java: -------------------------------------------------------------------------------- 1 | package com.example.intercomreactnative; 2 | 3 | 4 | import com.google.firebase.messaging.FirebaseMessagingService; 5 | import com.google.firebase.messaging.RemoteMessage; 6 | import com.intercom.reactnative.IntercomModule; 7 | 8 | public class MainNotificationService extends FirebaseMessagingService { 9 | 10 | @Override 11 | public void onNewToken(String refreshedToken) { 12 | IntercomModule.sendTokenToIntercom(getApplication(), refreshedToken); 13 | //DO LOGIC HERE 14 | } 15 | 16 | public void onMessageReceived(RemoteMessage remoteMessage) { 17 | if (IntercomModule.isIntercomPush(remoteMessage)) { 18 | IntercomModule.handleRemotePushMessage(getApplication(), remoteMessage); 19 | } else { 20 | //HANDLE NOT INTERCOM MESSAGE 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | buildToolsVersion = "35.0.0" 4 | minSdkVersion = 23 5 | compileSdkVersion = 35 6 | targetSdkVersion = 35 7 | ndkVersion = "26.1.10909125" 8 | kotlinVersion = "1.9.22" 9 | } 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle") 16 | classpath("com.facebook.react:react-native-gradle-plugin") 17 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 18 | } 19 | } 20 | 21 | apply plugin: "com.facebook.react.rootproject" 22 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Use this property to specify which architecture you want to build. 28 | # You can also override it from the CLI using 29 | # ./gradlew -PreactNativeArchitectures=x86_64 30 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 31 | # Use this property to enable support to the new architecture. 32 | # This will allow you to use TurboModules and the Fabric render in 33 | # your application. You should enable this flag either if you want 34 | # to write custom TurboModules/Fabric components OR use libraries that 35 | # are providing them. 36 | newArchEnabled=false 37 | FLIPPER_VERSION=0.93.0 38 | 39 | org.gradle.jvmargs=-Xmx2048m 40 | org.gradle.daemon=true 41 | org.gradle.parallel=true 42 | org.gradle.configureondemand=true 43 | # Use this property to enable or disable the Hermes JS engine. 44 | # If set to false, you will be using JSC instead. 45 | hermesEnabled=false 46 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'IntercomReactNativeExample' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | includeBuild('../node_modules/@react-native/gradle-plugin') 5 | 6 | include ':intercomreactnative' 7 | project(':intercomreactnative').projectDir = new File(rootProject.projectDir, '../../android') 8 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "IntercomReactNativeExample", 3 | "displayName": "IntercomReactNative Example" 4 | } 5 | -------------------------------------------------------------------------------- /example/assets/intercom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/example/assets/intercom.png -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const pak = require('../package.json'); 3 | 4 | module.exports = { 5 | presets: ['module:@react-native/babel-preset'], 6 | plugins: [ 7 | [ 8 | 'module-resolver', 9 | { 10 | extensions: ['.tsx', '.ts', '.js', '.json'], 11 | alias: { 12 | [pak.name]: path.join(__dirname, '..', pak.source), 13 | }, 14 | }, 15 | ], 16 | ], 17 | }; 18 | -------------------------------------------------------------------------------- /example/e2e/helpers.ts: -------------------------------------------------------------------------------- 1 | const scrollToElementByAccessibilityLabel = async (element: string) => { 2 | if (browser.isAndroid) { 3 | const bottomElementSelector = `new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().description("${element}"))`; 4 | await $(`android=${bottomElementSelector}`); 5 | } else { 6 | await browser.execute('mobile: scroll', { 7 | direction: 'down', 8 | name: `~${element}`, 9 | }); 10 | } 11 | }; 12 | 13 | browser.addCommand( 14 | 'scrollToElementByAccessibilityLabel', 15 | scrollToElementByAccessibilityLabel 16 | ); 17 | 18 | const wait = async (milis: number) => 19 | new Promise((resolve) => setTimeout(resolve(), milis)); 20 | browser.addCommand('wait', wait); 21 | 22 | const clickWithDelay = async (element: string, milis: number) => { 23 | await wait(milis); 24 | await (await $(element)).click(); 25 | }; 26 | browser.addCommand('clickWithDelay', clickWithDelay); 27 | 28 | const waitForRoot = async () => { 29 | (await $('~app-root')).waitForDisplayed({ timeout: 12000 }); 30 | }; 31 | driver.addCommand('waitForRoot', waitForRoot); 32 | 33 | const boot = async () => { 34 | if (browser.isIOS) { 35 | await (await $('~Allow')).waitForDisplayed({ timeout: 12000 }); 36 | await (await $('~Allow')).click(); 37 | } 38 | }; 39 | driver.addCommand('boot', boot); 40 | 41 | const closeOverlay = async (customCloseButtonId?: string) => { 42 | const buttonId = browser.isAndroid ? `~Close` : customCloseButtonId || `~intercom close button`; 43 | 44 | const closeButton = await $(buttonId); 45 | await closeButton.waitForDisplayed({ timeout: 22000 }); 46 | await closeButton.click(); 47 | }; 48 | 49 | const closeModalOverlay = async (customCloseButtonId?: string) => { 50 | const buttonId = browser.isAndroid ? `~Close` : customCloseButtonId || `~intercom modal close button`; 51 | 52 | const closeButton = await $(buttonId); 53 | await closeButton.waitForDisplayed({ timeout: 22000 }); 54 | await closeButton.click(); 55 | }; 56 | 57 | browser.addCommand('closeOverlay', closeOverlay); 58 | browser.addCommand('closeModalOverlay', closeModalOverlay); 59 | 60 | const closeArticleOverlay = async () => { 61 | if (browser.isAndroid) { 62 | const closeButton = await $( 63 | `/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.widget.ImageButton` 64 | ); 65 | await closeButton.waitForDisplayed({ timeout: 22000 }); 66 | await closeButton.click(); 67 | } else { 68 | await closeModalOverlay(); 69 | } 70 | }; 71 | browser.addCommand('closeArticleOverlay', closeArticleOverlay); 72 | 73 | const closeHelpCenterOverlay = async () => { 74 | if (browser.isAndroid) { 75 | const closeButton = await $( 76 | `/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout/android.view.ViewGroup/android.view.ViewGroup/android.widget.ImageButton` 77 | ); 78 | await closeButton.waitForDisplayed({ timeout: 22000 }); 79 | await closeButton.click(); 80 | } else { 81 | await closeOverlay('~help center close button'); 82 | } 83 | }; 84 | browser.addCommand('closeHelpCenterOverlay', closeHelpCenterOverlay); 85 | 86 | const closeAlert = async () => { 87 | const elementId = browser.isAndroid 88 | ? '/hierarchy/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.ScrollView/android.widget.LinearLayout/android.widget.Button\n' 89 | : '~OK'; 90 | const alertButton = await $(elementId); 91 | await alertButton.waitForDisplayed({ timeout: 12000 }); 92 | await alertButton.click(); 93 | }; 94 | browser.addCommand('closeAlert', closeAlert); 95 | -------------------------------------------------------------------------------- /example/e2e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "e2e", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build:android": "../android/gradlew assembleFossRelease -p ../android", 8 | "build:ios": "xcodebuild build -workspace ../ios/IntercomReactNativeExample.xcworkspace -scheme IntercomReactNativeExampleUI -configuration Release -sdk iphonesimulator -derivedDataPath ./build", 9 | "test:android": "npx wdio ./wdio.android.conf.ts", 10 | "test:ios": "npx wdio ./wdio.ios.conf.ts" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "dependencies": { 16 | "@wdio/cli": "^9.5.1", 17 | "appium": "^2.14.1", 18 | "chai": "^4.3.4", 19 | "webdriver": "^7.16.13", 20 | "webdriverio": "^7.7.2" 21 | }, 22 | "devDependencies": { 23 | "@wdio/appium-service": "^9.5.1", 24 | "@wdio/local-runner": "^9.5.1", 25 | "@wdio/mocha-framework": "^7.7.3", 26 | "@wdio/spec-reporter": "^9.5.0", 27 | "chromedriver": "^131.0.4", 28 | "ts-node": "^10.0.0", 29 | "typescript": "^4.3.2", 30 | "wdio-chromedriver-service": "^8.1.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /example/e2e/types/wido.d.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | namespace WebdriverIO { 3 | interface Browser { 4 | boot: () => Promise; 5 | waitForRoot: () => Promise; 6 | scrollToElementByAccessibilityLabel: (element: string) => Promise; 7 | wait: (milis: number) => Promise; 8 | clickWithDelay: (element: string, milis: number) => Promise; 9 | closeHelpCenterOverlay: () => Promise; 10 | closeArticleOverlay: () => Promise; 11 | closeOverlay: (customCloseButtonId?: string) => Promise; 12 | closeAlert: () => Promise; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/e2e/wdio.android.conf.ts: -------------------------------------------------------------------------------- 1 | exports.config = { 2 | appium: { command: 'appium' }, 3 | 4 | runner: 'local', 5 | port: 4723, 6 | specs: ['./tests/**/*.e2e.ts'], 7 | exclude: [], 8 | maxInstances: 10, 9 | capabilities: [ 10 | { 11 | maxInstances: 1, 12 | browserName: '', 13 | platformName: 'Android', 14 | platformVersion: '10', 15 | deviceName: 'Android_29', 16 | app: '../android/app/build/outputs/apk/foss/release/app-foss-release.apk', 17 | automationName: 'UiAutomator2', 18 | }, 19 | ], 20 | logLevel: 'info', 21 | bail: 0, 22 | baseUrl: 'http://localhost', 23 | waitforTimeout: 10000, 24 | connectionRetryTimeout: 120000, 25 | connectionRetryCount: 3, 26 | services: ['appium'], 27 | framework: 'mocha', 28 | reporters: ['spec'], 29 | mochaOpts: { 30 | ui: 'bdd', 31 | timeout: 60000, 32 | }, 33 | before() { 34 | require('./helpers'); 35 | }, 36 | featureFlags: { 37 | specFiltering: true, 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /example/e2e/wdio.ios.conf.ts: -------------------------------------------------------------------------------- 1 | exports.config = { 2 | appium: { command: 'appium' }, 3 | 4 | runner: 'local', 5 | port: 4723, 6 | specs: ['./tests/**/*.e2e.ts'], 7 | exclude: [], 8 | maxInstances: 10, 9 | capabilities: [ 10 | { 11 | maxInstances: 1, 12 | browserName: '', 13 | automationName: 'XCUITest', 14 | platformName: 'iOS', 15 | platformVersion: '16.0', 16 | deviceName: 'iPhone 14', 17 | app: 'build/Build/Products/Release-iphonesimulator/IntercomReactNativeExampleUI.app', 18 | }, 19 | ], 20 | logLevel: 'info', 21 | bail: 0, 22 | baseUrl: 'http://localhost', 23 | waitforTimeout: 10000, 24 | connectionRetryTimeout: 220000, 25 | connectionRetryCount: 3, 26 | services: ['appium'], 27 | framework: 'mocha', 28 | reporters: ['spec'], 29 | mochaOpts: { 30 | ui: 'bdd', 31 | timeout: 60000, 32 | }, 33 | before() { 34 | require('./helpers'); 35 | }, 36 | featureFlags: { 37 | specFiltering: true, 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /example/index.tsx: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | import App from './src/App'; 3 | import { name as appName } from './app.json'; 4 | 5 | AppRegistry.registerComponent(appName, () => App); 6 | -------------------------------------------------------------------------------- /example/ios/File.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // IntercomReactNativeExample 4 | // 5 | 6 | import Foundation 7 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample.xcodeproj/xcshareddata/xcschemes/IntercomReactNativeExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 51 | 52 | 53 | 54 | 55 | 56 | 66 | 68 | 74 | 75 | 76 | 79 | 80 | 81 | 87 | 89 | 95 | 96 | 97 | 98 | 100 | 101 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample.xcodeproj/xcshareddata/xcschemes/IntercomReactNativeExampleUI.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 46 | 47 | 57 | 59 | 65 | 66 | 67 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (nonatomic, strong) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import "AppDelegate.h" 9 | 10 | #if RCT_DEV 11 | #import 12 | #endif 13 | 14 | #import 15 | #import 16 | #import 17 | #import 18 | #import 19 | #import 20 | #import "RNCConfig.h" 21 | 22 | #ifdef FB_SONARKIT_ENABLED 23 | 24 | #import 25 | #import 26 | #import 27 | #import 28 | #import 29 | #import 30 | 31 | static void InitializeFlipper(UIApplication *application) { 32 | FlipperClient *client = [FlipperClient sharedClient]; 33 | SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; 34 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]]; 35 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; 36 | [client addPlugin:[FlipperKitReactPlugin new]]; 37 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; 38 | [client start]; 39 | } 40 | 41 | #endif 42 | 43 | @implementation AppDelegate 44 | 45 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 46 | #ifdef FB_SONARKIT_ENABLED 47 | InitializeFlipper(application); 48 | #endif 49 | 50 | NSMutableDictionary *newLaunchOptions = [NSMutableDictionary dictionaryWithDictionary:launchOptions]; 51 | 52 | // Modifying launchOptions to facilitate deep linking. 53 | if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) { 54 | NSDictionary *remoteNotif = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]; 55 | if (remoteNotif[@"uri"]) { 56 | NSString *initialURL = remoteNotif[@"uri"]; 57 | if (!launchOptions[UIApplicationLaunchOptionsURLKey]) { 58 | newLaunchOptions[UIApplicationLaunchOptionsURLKey] = [NSURL URLWithString:initialURL]; 59 | } 60 | } 61 | } 62 | 63 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:newLaunchOptions]; 64 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 65 | moduleName:@"IntercomReactNativeExample" 66 | initialProperties:nil]; 67 | 68 | if (@available(iOS 13.0, *)) { 69 | rootView.backgroundColor = [UIColor systemBackgroundColor]; 70 | } else { 71 | rootView.backgroundColor = [UIColor whiteColor]; 72 | } 73 | 74 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 75 | UIViewController *rootViewController = [UIViewController new]; 76 | rootViewController.view = rootView; 77 | self.window.rootViewController = rootViewController; 78 | NSString *apiKey = [RNCConfig envFor:@"IOS_INTERCOM_KEY"]; 79 | NSString *appId = [RNCConfig envFor:@"IOS_INTERCOM_APP_ID"]; 80 | 81 | [IntercomModule initialize:apiKey withAppId:appId]; 82 | 83 | [self.window makeKeyAndVisible]; 84 | 85 | UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; 86 | [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound) 87 | completionHandler:^(BOOL granted, NSError *_Nullable error) { 88 | }]; 89 | [[UIApplication sharedApplication] registerForRemoteNotifications]; 90 | 91 | 92 | return YES; 93 | } 94 | 95 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 96 | [IntercomModule setDeviceToken:deviceToken]; 97 | } 98 | 99 | - (BOOL)application:(UIApplication *)application 100 | openURL:(NSURL *)url 101 | options:(NSDictionary *)options { 102 | return [RCTLinkingManager application:application openURL:url options:options]; 103 | } 104 | 105 | - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity 106 | restorationHandler:(nonnull void (^)(NSArray> *_Nullable))restorationHandler { 107 | return [RCTLinkingManager application:application 108 | continueUserActivity:userActivity 109 | restorationHandler:restorationHandler]; 110 | } 111 | 112 | 113 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { 114 | #if DEBUG 115 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 116 | #else 117 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 118 | #endif 119 | } 120 | 121 | @end 122 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | IntercomReactNative Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleURLTypes 24 | 25 | 26 | CFBundleTypeRole 27 | Editor 28 | CFBundleURLName 29 | intercom 30 | CFBundleURLSchemes 31 | 32 | intercom 33 | 34 | 35 | 36 | CFBundleVersion 37 | 1 38 | IntercomUniversalLinkDomains 39 | 40 | intercom.com 41 | 42 | LSRequiresIPhoneOS 43 | 44 | NSAppTransportSecurity 45 | 46 | NSExceptionDomains 47 | 48 | localhost 49 | 50 | NSExceptionAllowsInsecureHTTPLoads 51 | 52 | 53 | 54 | 55 | NSLocationWhenInUseUsageDescription 56 | 57 | NSPhotoLibraryUsageDescription 58 | Send photos to support center 59 | UIBackgroundModes 60 | 61 | remote-notification 62 | 63 | UILaunchStoryboardName 64 | LaunchScreen 65 | UIRequiredDeviceCapabilities 66 | 67 | armv7 68 | 69 | UISupportedInterfaceOrientations 70 | 71 | UIInterfaceOrientationPortrait 72 | UIInterfaceOrientationLandscapeLeft 73 | UIInterfaceOrientationLandscapeRight 74 | 75 | UIViewControllerBasedStatusBarAppearance 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample/IntercomReactNativeExample.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample/IntercomReactNativeExampleRelease.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | production 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExample/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /example/ios/IntercomReactNativeExampleUIRelease.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 2 | require_relative '../node_modules/react-native/scripts/react_native_pods' 3 | 4 | platform :ios, '15.0' 5 | use_native_modules! 6 | 7 | target 'IntercomReactNativeExample' do 8 | config = use_native_modules! 9 | 10 | use_react_native!( 11 | :path => config[:reactNativePath], 12 | # to enable hermes on iOS, change `false` to `true` and then install pods 13 | :hermes_enabled => false 14 | ) 15 | 16 | pod 'intercom-react-native', :path => '../..' 17 | 18 | # Enables Flipper. 19 | # 20 | # Note that if you have use_frameworks! enabled, Flipper will not work and 21 | # you should disable the next line. 22 | # use_flipper!( ) 23 | 24 | post_install do |installer| 25 | react_native_post_install(installer) 26 | 27 | 28 | # Apple Silicon builds require a library path tweak for Swift library discovery or "symbol not found" for swift things 29 | installer.aggregate_targets.each do |aggregate_target| 30 | aggregate_target.user_project.native_targets.each do |target| 31 | target.build_configurations.each do |config| 32 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0' 33 | config.build_settings['LIBRARY_SEARCH_PATHS'] = ['$(SDKROOT)/usr/lib/swift', '$(inherited)'] 34 | end 35 | end 36 | aggregate_target.user_project.save 37 | end 38 | 39 | # Flipper requires a crude patch to bump up iOS deployment target, or "error: thread-local storage is not supported for the current target" 40 | # I'm not aware of any other way to fix this one other than bumping iOS deployment target to match react-native (iOS 15 now) 41 | installer.pods_project.targets.each do |target| 42 | target.build_configurations.each do |config| 43 | # Setting deployment target to iOS 11 for RCT-Folly to avoid errors with Flipper. 44 | if ['RCT-Folly'].include? target.name 45 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0' 46 | end 47 | config.build_settings['GCC_WARN_INHIBIT_ALL_WARNINGS'] = 'YES' 48 | config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', '_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION'] 49 | end 50 | end 51 | 52 | # ...but if you bump iOS deployment target, Flipper barfs again "Time.h:52:17: error: typedef redefinition with different types" 53 | # We need to make one crude patch to RCT-Folly - set `__IPHONE_10_0` to our iOS target + 1 54 | # https://github.com/facebook/flipper/issues/834 - 84 comments and still going... 55 | `sed -i -e $'s/__IPHONE_10_0/__IPHONE_12_0/' Pods/RCT-Folly/folly/portability/Time.h` 56 | 57 | end 58 | end 59 | 60 | target 'IntercomReactNativeExampleUI' do 61 | config = use_native_modules! 62 | 63 | use_react_native!( 64 | :path => config[:reactNativePath], 65 | # to enable hermes on iOS, change `false` to `true` and then install pods 66 | :hermes_enabled => false 67 | ) 68 | 69 | pod 'intercom-react-native', :path => '../..' 70 | end 71 | -------------------------------------------------------------------------------- /example/ios/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryFileTimestamp 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | C617.1 13 | 14 | 15 | 16 | NSPrivacyAccessedAPIType 17 | NSPrivacyAccessedAPICategoryUserDefaults 18 | NSPrivacyAccessedAPITypeReasons 19 | 20 | CA92.1 21 | 22 | 23 | 24 | NSPrivacyAccessedAPIType 25 | NSPrivacyAccessedAPICategorySystemBootTime 26 | NSPrivacyAccessedAPITypeReasons 27 | 28 | 35F9.1 29 | 30 | 31 | 32 | NSPrivacyCollectedDataTypes 33 | 34 | NSPrivacyTracking 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); 2 | const path = require('path'); 3 | const root = path.resolve(__dirname, '..'); 4 | const pak = require('../package.json'); 5 | /** 6 | * Metro configuration 7 | * https://facebook.github.io/metro/docs/configuration 8 | * 9 | * @type {import('metro-config').MetroConfig} 10 | */ 11 | const modules = Object.keys({ 12 | ...pak.peerDependencies, 13 | }); 14 | const config = { 15 | resolver: { 16 | extraNodeModules: modules.reduce((acc, name) => { 17 | acc[name] = path.join(__dirname, 'node_modules', name); 18 | return acc; 19 | }, {}), 20 | }, 21 | watchFolders: [root], 22 | }; 23 | 24 | module.exports = mergeConfig(getDefaultConfig(__dirname), config); 25 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "intercom-react-native-example", 3 | "description": "Example app for intercom-react-native", 4 | "version": "0.0.1", 5 | "private": true, 6 | "scripts": { 7 | "android": "react-native run-android", 8 | "ios": "react-native run-ios", 9 | "start": "react-native start" 10 | }, 11 | "dependencies": { 12 | "@react-native-async-storage/async-storage": "^1.23.1", 13 | "@react-native-community/cli": "^13.6.6", 14 | "node-fetch": "^2.6.1", 15 | "react-native": "0.74.0", 16 | "react-native-config": "^1.5.1" 17 | }, 18 | "devDependencies": { 19 | "@babel/core": "^7.20.0", 20 | "@babel/preset-env": "^7.20.0", 21 | "@babel/runtime": "^7.27.4", 22 | "@react-native/babel-preset": "0.74.83", 23 | "@react-native/eslint-config": "0.74.83", 24 | "@react-native/metro-config": "0.74.83", 25 | "@react-native/typescript-config": "0.74.83", 26 | "@types/react": "^18.2.6", 27 | "@types/react-test-renderer": "^18.0.0", 28 | "@wdio/cli": "^9.5.1", 29 | "@wdio/local-runner": "^9.5.1", 30 | "@wdio/mocha-framework": "^8.33.0", 31 | "@wdio/spec-reporter": "^8.32.4", 32 | "babel-plugin-module-resolver": "^5.0.0", 33 | "chromedriver": "^132.0.0", 34 | "metro-react-native-babel-preset": "^0.77.0", 35 | "react-native-codegen": "^0.70.7", 36 | "wdio-chromedriver-service": "^8.1.1", 37 | "webdriverio": "^9.5.1" 38 | }, 39 | "engines": { 40 | "node": ">=18" 41 | }, 42 | "packageManager": "yarn@3.6.4" 43 | } 44 | -------------------------------------------------------------------------------- /example/scripts/generateEnv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo IOS_INTERCOM_APP_ID=$IOS_INTERCOM_APP_ID >>.env 4 | echo IOS_INTERCOM_KEY=$IOS_INTERCOM_KEY >>.env 5 | echo ANDROID_INTERCOM_APP_ID=$ANDROID_INTERCOM_APP_ID >>.env 6 | echo ANDROID_INTERCOM_KEY=$ANDROID_INTERCOM_KEY >>.env 7 | echo CAROUSEL_ID=$CAROUSEL_ID >>.env 8 | echo SURVEY_ID=$SURVEY_ID >>.env 9 | echo EVENT_NAME=$EVENT_NAME >>.env 10 | echo ARTICLE_ID=$ARTICLE_ID >>.env 11 | echo USER_NAME=$USER_NAME >>.env 12 | echo SEARCH_TERM=$SEARCH_TERM >>.env 13 | echo COLLECTION_ID=$COLLECTION_ID >>.env 14 | -------------------------------------------------------------------------------- /example/src/components/Button.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo, useCallback } from 'react'; 2 | import { 3 | TouchableOpacity as RNTouchableOpacity, 4 | StyleSheet, 5 | Text as RNText, 6 | } from 'react-native'; 7 | 8 | // @ts-ignore 9 | function Button(props) { 10 | const { 11 | intercom_title, 12 | intercom_disabled, 13 | intercom_onPress, 14 | intercom_accesibilityLabel, 15 | } = props; 16 | const onPress = useCallback(() => { 17 | intercom_onPress(); 18 | }, [intercom_onPress]); 19 | 20 | return ( 21 | 27 | 28 | {intercom_title} 29 | 30 | 31 | ); 32 | } 33 | 34 | // @ts-ignore 35 | export const buttonStyles = (props) => 36 | StyleSheet.create({ 37 | touchableOpacity: { 38 | backgroundColor: props.intercom_disabled ? '#f4f4f4' : '#0096FF', 39 | borderRadius: 5, 40 | padding: 8, 41 | justifyContent: 'center', 42 | alignItems: 'center', 43 | marginTop: 3, 44 | marginBottom: 3, 45 | }, 46 | text: { 47 | color: props.intercom_disabled ? '#808080' : 'white', 48 | }, 49 | }); 50 | 51 | export default memo(Button); 52 | -------------------------------------------------------------------------------- /example/src/components/Input.tsx: -------------------------------------------------------------------------------- 1 | import type { TextInputProps } from 'react-native'; 2 | import React from 'react'; 3 | import { StyleSheet, View, TextInput, Text } from 'react-native'; 4 | 5 | const Input = ({ 6 | title, 7 | style, 8 | ...props 9 | }: TextInputProps & { title: string }) => { 10 | return ( 11 | 12 | {title && {title}} 13 | 14 | 15 | ); 16 | }; 17 | 18 | const styles = StyleSheet.create({ 19 | container: { marginVertical: 8 }, 20 | title: { 21 | marginBottom: 3, 22 | }, 23 | input: { 24 | borderWidth: 1, 25 | borderColor: 'black', 26 | paddingHorizontal: 8, 27 | paddingVertical: 4, 28 | borderRadius: 4, 29 | backgroundColor: 'white', 30 | color: '#808080', 31 | }, 32 | }); 33 | 34 | export default Input; 35 | -------------------------------------------------------------------------------- /example/src/constants.tsx: -------------------------------------------------------------------------------- 1 | import Config from 'react-native-config'; 2 | import { Platform } from 'react-native'; 3 | 4 | export const CAROUSEL_ID = Config.CAROUSEL_ID; 5 | export const SURVEY_ID = Config.SURVEY_ID; 6 | export const EVENT_NAME = Config.EVENT_NAME; 7 | export const CONVERSATION_ID = Config.CONVERSATION_ID; 8 | export const ARTICLE_ID = Config.ARTICLE_ID; 9 | export const USER_NAME = Config.USER_NAME; 10 | export const COLLECTION_ID = Config.COLLECTION_ID; 11 | export const SEARCH_TERM = Config.SEARCH_TERM; 12 | export const TOKEN = Platform.select({ 13 | ios: 'RN-IOS-TOKEN', 14 | default: 'RN-ANDROID-TOKEN', 15 | }); 16 | -------------------------------------------------------------------------------- /intercom-react-native.podspec: -------------------------------------------------------------------------------- 1 | 2 | require "json" 3 | 4 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 5 | 6 | Pod::Spec.new do |s| 7 | s.name = "intercom-react-native" 8 | s.version = package["version"] 9 | s.summary = package["description"] 10 | s.homepage = package["homepage"] 11 | s.license = package["license"] 12 | s.authors = package["author"] 13 | 14 | s.platforms = { :ios => "15.0" } 15 | s.source = { :git => "https://github.com/intercom/intercom-react-native.git", :tag => "#{s.version}" } 16 | 17 | s.source_files = "ios/**/*.{h,m,mm}" 18 | s.resource_bundles = { 'IntercomFramework' => ['ios/assets/*'] } 19 | 20 | s.pod_target_xcconfig = { "DEFINES_MODULE" => "YES" } 21 | 22 | s.dependency "React-Core" 23 | s.dependency "Intercom", '~> 18.6.1' 24 | end 25 | -------------------------------------------------------------------------------- /ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /ios/IntercomAttributesBuilder.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface IntercomAttributesBuilder : NSObject 5 | + (ICMUserAttributes *)userAttributesForDictionary:(NSDictionary *)attributesDict; 6 | + (NSMutableDictionary *)dictionaryForUserAttributes:(ICMUserAttributes *)attributes; 7 | @end 8 | -------------------------------------------------------------------------------- /ios/IntercomEventEmitter.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface IntercomEventEmitter : RCTEventEmitter 4 | @end 5 | -------------------------------------------------------------------------------- /ios/IntercomEventEmitter.m: -------------------------------------------------------------------------------- 1 | #import "IntercomEventEmitter.h" 2 | #import 3 | 4 | 5 | @implementation IntercomEventEmitter 6 | 7 | RCT_EXPORT_MODULE(); 8 | 9 | + (BOOL)requiresMainQueueSetup { 10 | return NO; 11 | } 12 | 13 | - (NSDictionary *)constantsToExport { 14 | return @{@"UNREAD_COUNT_CHANGE_NOTIFICATION": IntercomUnreadConversationCountDidChangeNotification, 15 | @"WINDOW_DID_HIDE_NOTIFICATION": IntercomWindowDidHideNotification, 16 | @"WINDOW_DID_SHOW_NOTIFICATION": IntercomWindowDidShowNotification 17 | }; 18 | } 19 | 20 | - (NSArray *)supportedEvents { 21 | return @[IntercomUnreadConversationCountDidChangeNotification, 22 | IntercomWindowDidHideNotification, IntercomWindowDidShowNotification]; 23 | } 24 | 25 | - (void)handleUpdateUnreadCount:(NSNotification *)notification { 26 | NSUInteger unreadCount = [Intercom unreadConversationCount]; 27 | NSNumber *unreadCountNumber = @(unreadCount); 28 | [self sendEventWithName:IntercomUnreadConversationCountDidChangeNotification body:@{@"count": unreadCountNumber}]; 29 | } 30 | 31 | - (void)handleWindowDidHideNotification:(NSNotification *)notification { 32 | [self sendEventWithName:IntercomWindowDidHideNotification body:@{@"visible": @NO}]; 33 | } 34 | 35 | - (void)handleWindowShowHideNotification:(NSNotification *)notification { 36 | [self sendEventWithName:IntercomWindowDidShowNotification body:@{@"visible": @YES}]; 37 | } 38 | 39 | // Will be called when this module's first listener is added. 40 | - (void)startObserving { 41 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleUpdateUnreadCount:) name:IntercomUnreadConversationCountDidChangeNotification object:nil]; 42 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleWindowDidHideNotification:) name:IntercomWindowDidHideNotification object:nil]; 43 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleWindowShowHideNotification:) name:IntercomWindowDidShowNotification object:nil]; 44 | } 45 | 46 | // Will be called when this module's last listener is removed, or on dealloc. 47 | - (void)stopObserving { 48 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 49 | } 50 | 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /ios/IntercomHelpCenterHelpers.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface IntercomHelpCenterHelpers : NSObject 5 | + (NSMutableArray *)parseCollectionsToArray:(NSArray *)collections; 6 | + (NSMutableArray *)parseArticlesToArray:(NSArray *)articlesArray; 7 | + (NSMutableDictionary *)parseHelpCenterCollectionToDictionary:(ICMHelpCenterCollectionContent *)collectionContent; 8 | + (NSMutableArray *)parseHelpCenterArticleSearchResultToArray:(NSArray*)articleArray; 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /ios/IntercomHelpCenterHelpers.m: -------------------------------------------------------------------------------- 1 | #import "IntercomHelpCenterHelpers.h" 2 | #import 3 | 4 | @implementation IntercomHelpCenterHelpers 5 | 6 | + (NSMutableArray *)parseCollectionsToArray:(NSArray *)collections { 7 | NSMutableArray *parsedCollections = [NSMutableArray arrayWithCapacity:[collections count]]; 8 | 9 | for (ICMHelpCenterCollection *collectionObject in collections) { 10 | NSMutableDictionary *item = [NSMutableDictionary dictionary]; 11 | [item setValue:[collectionObject collectionId] forKey:@"id"]; 12 | [item setValue:[collectionObject title] forKey:@"title"]; 13 | [item setValue:[collectionObject summary] forKey:@"summary"]; 14 | [parsedCollections addObject:item]; 15 | } 16 | return parsedCollections; 17 | } 18 | 19 | + (NSMutableArray *)parseArticlesToArray:(NSArray *)articlesArray { 20 | 21 | NSMutableArray *parsedArticles = [NSMutableArray arrayWithCapacity:[articlesArray count]]; 22 | for (ICMHelpCenterArticle *articleObject in articlesArray) { 23 | NSMutableDictionary *articleItem = [NSMutableDictionary dictionary]; 24 | [articleItem setValue:[articleObject articleId] forKey:@"id"]; 25 | [articleItem setValue:[articleObject title] forKey:@"title"]; 26 | [parsedArticles addObject:articleItem]; 27 | } 28 | 29 | return parsedArticles; 30 | } 31 | 32 | + (NSMutableDictionary *)parseHelpCenterCollectionToDictionary:(ICMHelpCenterCollectionContent *)collectionContent { 33 | 34 | NSMutableDictionary *item = [NSMutableDictionary dictionary]; 35 | [item setValue:[collectionContent collectionId] forKey:@"id"]; 36 | [item setValue:[collectionContent title] forKey:@"title"]; 37 | [item setValue:[collectionContent summary] forKey:@"summary"]; 38 | [item setValue:[self parseArticlesToArray:[collectionContent articles]] forKey:@"articles"]; 39 | [item setValue:[self parseCollectionsToArray:[collectionContent collections]] forKey:@"collections"]; 40 | 41 | return item; 42 | } 43 | 44 | + (NSMutableArray *)parseHelpCenterArticleSearchResultToArray:(NSArray*)articleArray { 45 | 46 | NSMutableArray *parsedArticles = [NSMutableArray arrayWithCapacity:[articleArray count]]; 47 | for (ICMHelpCenterArticleSearchResult *articleObject in articleArray) { 48 | NSMutableDictionary *articleItem = [NSMutableDictionary dictionary]; 49 | [articleItem setValue:[articleObject title] forKey:@"title"]; 50 | [articleItem setValue:[articleObject articleId] forKey:@"id"]; 51 | [articleItem setValue:[articleObject matchingSnippet] forKey:@"matchingSnippet"]; 52 | [articleItem setValue:[articleObject summary] forKey:@"summary"]; 53 | [parsedArticles addObject:articleItem]; 54 | } 55 | 56 | return parsedArticles; 57 | } 58 | 59 | 60 | @end 61 | 62 | -------------------------------------------------------------------------------- /ios/IntercomModule.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface IntercomModule : NSObject 4 | + (void)initialize:(nonnull NSString *)apiKey withAppId:(nonnull NSString *)appId; 5 | + (void)setDeviceToken:(nonnull NSData *)deviceToken; 6 | + (BOOL)isIntercomPushNotification:(nonnull NSDictionary *)userInfo; 7 | + (void)handleIntercomPushNotification:(nonnull NSDictionary *)userInfo; 8 | - (NSError *)exceptionToError:(NSException *)exception :(NSString *)code :(NSString *)domain; 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@intercom/intercom-react-native", 3 | "version": "8.5.0", 4 | "description": "React Native wrapper to bridge our iOS and Android SDK", 5 | "main": "lib/commonjs/index", 6 | "module": "lib/module/index", 7 | "types": "lib/typescript/index.d.ts", 8 | "react-native": "src/index", 9 | "source": "src/index", 10 | "files": [ 11 | "src", 12 | "lib", 13 | "android", 14 | "ios", 15 | "cpp", 16 | "app.plugin.js", 17 | "intercom-react-native.podspec", 18 | "!lib/typescript/example", 19 | "!android/build", 20 | "!ios/build", 21 | "!**/__tests__", 22 | "!**/__fixtures__", 23 | "!**/__mocks__" 24 | ], 25 | "scripts": { 26 | "test": "echo test", 27 | "typescript": "tsc --noEmit", 28 | "lint": "eslint \"**/*.{js,ts,tsx}\"", 29 | "prepare": "bob build", 30 | "example": "yarn --cwd example", 31 | "pods": "cd example && pod-install --quiet", 32 | "bootstrap": "yarn example && yarn && yarn pods" 33 | }, 34 | "keywords": [ 35 | "react-native", 36 | "ios", 37 | "intercom", 38 | "messenger", 39 | "help center", 40 | "articles", 41 | "push notifications", 42 | "customer support", 43 | "android" 44 | ], 45 | "repository": "https://github.com/intercom/intercom-react-native", 46 | "author": "Intercom (https://www.intercom.com/)", 47 | "license": "MIT", 48 | "bugs": { 49 | "url": "https://www.intercom.com/" 50 | }, 51 | "homepage": "https://www.intercom.com/", 52 | "publishConfig": { 53 | "registry": "https://registry.npmjs.org/", 54 | "access": "public" 55 | }, 56 | "devDependencies": { 57 | "@expo/config-plugins": "^7.9.1", 58 | "@react-native-community/eslint-config": "3.2.0", 59 | "@react-native/typescript-config": "0.73.1", 60 | "@types/jest": "29.5.12", 61 | "@types/mocha": "10.0.6", 62 | "@types/react": "18.2.6", 63 | "@wdio/globals": "9.5.1", 64 | "@wdio/mocha-framework": "8.33.1", 65 | "eslint": "8.19.0", 66 | "eslint-config-prettier": "8.10.0", 67 | "eslint-plugin-prettier": "5.1.3", 68 | "jest": "29.6.3", 69 | "metro-react-native-babel-preset": "^0.77.0", 70 | "pod-install": "0.2.0", 71 | "prettier": "3.0.0", 72 | "react": "18.2.0", 73 | "react-native": "^0.74.0", 74 | "react-native-builder-bob": "0.23.2", 75 | "typescript": "5.0.4", 76 | "webdriverio": "9.5.1" 77 | }, 78 | "peerDependencies": { 79 | "react": "*", 80 | "react-native": "*" 81 | }, 82 | "jest": { 83 | "preset": "react-native", 84 | "modulePathIgnorePatterns": [ 85 | "/example/node_modules", 86 | "/sandboxes/node_modules", 87 | "/lib/" 88 | ] 89 | }, 90 | "eslintConfig": { 91 | "root": true, 92 | "ignorePatterns": [ 93 | "example/e2e/**" 94 | ], 95 | "env": { 96 | "mocha": true 97 | }, 98 | "extends": [ 99 | "@react-native-community", 100 | "prettier" 101 | ], 102 | "rules": { 103 | "prettier/prettier": [ 104 | "error", 105 | { 106 | "quoteProps": "consistent", 107 | "singleQuote": true, 108 | "tabWidth": 2, 109 | "trailingComma": "es5", 110 | "useTabs": false 111 | } 112 | ] 113 | } 114 | }, 115 | "eslintIgnore": [ 116 | "node_modules/", 117 | "lib/", 118 | "sandboxes/" 119 | ], 120 | "prettier": { 121 | "quoteProps": "consistent", 122 | "singleQuote": true, 123 | "tabWidth": 2, 124 | "trailingComma": "es5", 125 | "useTabs": false 126 | }, 127 | "react-native-builder-bob": { 128 | "source": "src", 129 | "output": "lib", 130 | "targets": [ 131 | "commonjs", 132 | "module", 133 | [ 134 | "typescript", 135 | { 136 | "project": "tsconfig.build.json" 137 | } 138 | ] 139 | ] 140 | }, 141 | "resolutions": { 142 | "@types/react": "18.2.6", 143 | "string-width": "4.2.3", 144 | "wrap-ansi": "7.0.0" 145 | }, 146 | "engines": { 147 | "node": ">=18" 148 | }, 149 | "dependencies": { 150 | "node-fetch": "^2.6.1" 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /sandboxes/IntercomExpo/.gitignore: -------------------------------------------------------------------------------- 1 | # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files 2 | 3 | # dependencies 4 | node_modules/ 5 | 6 | # android and iOS folders 7 | android/ 8 | ios/ 9 | 10 | # Expo 11 | .expo/ 12 | dist/ 13 | web-build/ 14 | 15 | # Native 16 | *.orig.* 17 | *.jks 18 | *.p8 19 | *.p12 20 | *.key 21 | *.mobileprovision 22 | 23 | # Metro 24 | .metro-health-check* 25 | 26 | # debug 27 | npm-debug.* 28 | yarn-debug.* 29 | yarn-error.* 30 | 31 | # macOS 32 | .DS_Store 33 | *.pem 34 | 35 | # local env files 36 | .env*.local 37 | 38 | # typescript 39 | *.tsbuildinfo 40 | -------------------------------------------------------------------------------- /sandboxes/IntercomExpo/App.styles.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | export const styles = StyleSheet.create({ 4 | screenWrapper: { 5 | alignItems: 'center', 6 | paddingLeft: 10, 7 | paddingRight: 10, 8 | }, 9 | rowWrapper: { 10 | flexDirection: 'row', 11 | marginTop: 10, 12 | alignContent: 'center', 13 | alignItems: 'center', 14 | justifyContent: 'center', 15 | }, 16 | title: { 17 | fontWeight: 'bold', 18 | fontSize: 16, 19 | marginBottom: 10, 20 | }, 21 | wrapper: { 22 | width: '100%', 23 | }, 24 | emailInput: { 25 | borderWidth: 1, 26 | borderColor: 'rgba(0,0,80,0.2)', 27 | backgroundColor: '#f3f8ff', 28 | paddingVertical: 5, 29 | paddingLeft: 5, 30 | fontSize: 18, 31 | marginBottom: 10, 32 | maxWidth: '100%', 33 | width: '100%', 34 | }, 35 | input: { 36 | borderWidth: 1, 37 | borderColor: 'rgba(0,0,80,0.2)', 38 | paddingVertical: 5, 39 | paddingLeft: 5, 40 | fontSize: 15, 41 | width: '45%', 42 | }, 43 | button: { 44 | backgroundColor: '#be2ed6', 45 | padding: 10, 46 | alignItems: 'center', 47 | borderRadius: 5, 48 | margin: 5, 49 | }, 50 | buttonText: { 51 | color: '#fff', 52 | }, 53 | divider: { 54 | marginVertical: 18, 55 | borderWidth: 0.5, 56 | borderColor: '#5757ca', 57 | }, 58 | modalContainer: { 59 | flex: 1, 60 | justifyContent: 'center', 61 | alignItems: 'center', 62 | backgroundColor: 'rgba(0, 0, 0, 0.5)', 63 | }, 64 | modalContent: { 65 | backgroundColor: 'white', 66 | padding: 20, 67 | borderRadius: 10, 68 | alignItems: 'center', 69 | width: '50%', 70 | }, 71 | }); 72 | -------------------------------------------------------------------------------- /sandboxes/IntercomExpo/App.utils.js: -------------------------------------------------------------------------------- 1 | import { MMKVLoader } from 'react-native-mmkv-storage'; 2 | 3 | export const storage = new MMKVLoader().initialize(); 4 | -------------------------------------------------------------------------------- /sandboxes/IntercomExpo/README.md: -------------------------------------------------------------------------------- 1 | # Intercom React Native Expo Sandbox 2 | 3 | # Setup 4 | 5 | ## Step 1: Install dependencies 6 | 7 | ```shell 8 | # using npm 9 | npm install 10 | 11 | # OR using Yarn 12 | yarn install 13 | ``` 14 | 15 | ## Step 2: Add your app id and api keys 16 | 17 | Go to `app.json` and replace the `appId`, `androidApiKey` and `iosApiKey` under `plugins`. 18 | You can also change the intercomRegion to US, EU or AU. 19 | Check our docs for a detailed explanation about these fields [here](https://developers.intercom.com/installing-intercom/react-native/installation/#using-intercom-with-expo) 20 | 21 | ```shell 22 | "plugins": [ 23 | [ 24 | "@intercom/intercom-react-native", 25 | { 26 | "appId": "", 27 | "androidApiKey": "", 28 | "iosApiKey": "", 29 | "intercomRegion": "US" 30 | } 31 | ] 32 | ], 33 | ``` 34 | 35 | ## Step 3: Prebuild the app 36 | 37 | ```shell 38 | # using npx 39 | npx expo prebuild 40 | 41 | # OR using Yarn 42 | yarn expo prebuild 43 | ``` 44 | 45 | ## Step 4: Run pod install 46 | 47 | Go to the `ios` folder and run pod install 48 | 49 | ```shell 50 | npx pod install 51 | ``` 52 | 53 | ## Step 5: Run the app 54 | 55 | ### For Android 56 | 57 | ```shell 58 | # using npm 59 | npx expo run:android 60 | 61 | # OR using Yarn 62 | yarn expo run:android 63 | ``` 64 | 65 | ### For iOS 66 | 67 | ```shell 68 | # using npm 69 | npx expo run:ios 70 | 71 | # OR using Yarn 72 | yarn expo run:ios 73 | ``` 74 | -------------------------------------------------------------------------------- /sandboxes/IntercomExpo/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "plugins": [ 4 | [ 5 | "@intercom/intercom-react-native", 6 | { 7 | "appId": "", 8 | "androidApiKey": "", 9 | "iosApiKey": "", 10 | "intercomRegion": "US" 11 | } 12 | ], 13 | [ 14 | "expo-build-properties", 15 | { 16 | "ios": { 17 | "deploymentTarget": "15.0" 18 | } 19 | } 20 | ] 21 | ], 22 | "name": "IntercomExpo", 23 | "slug": "IntercomExpo", 24 | "version": "1.0.0", 25 | "orientation": "portrait", 26 | "icon": "./assets/icon.png", 27 | "userInterfaceStyle": "light", 28 | "splash": { 29 | "image": "./assets/splash.png", 30 | "resizeMode": "contain", 31 | "backgroundColor": "#ffffff" 32 | }, 33 | "assetBundlePatterns": [ 34 | "**/*" 35 | ], 36 | "ios": { 37 | "supportsTablet": true, 38 | "bundleIdentifier": "io.intercom.ios.enterprise.sample" 39 | }, 40 | "android": { 41 | "adaptiveIcon": { 42 | "foregroundImage": "./assets/adaptive-icon.png", 43 | "backgroundColor": "#ffffff" 44 | }, 45 | "permissions": [ 46 | "android.permission.READ_EXTERNAL_STORAGE", 47 | "android.permission.VIBRATE" 48 | ], 49 | "package": "com.intercom.sample" 50 | }, 51 | "web": { 52 | "favicon": "./assets/favicon.png" 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /sandboxes/IntercomExpo/assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/IntercomExpo/assets/adaptive-icon.png -------------------------------------------------------------------------------- /sandboxes/IntercomExpo/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/IntercomExpo/assets/favicon.png -------------------------------------------------------------------------------- /sandboxes/IntercomExpo/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/IntercomExpo/assets/icon.png -------------------------------------------------------------------------------- /sandboxes/IntercomExpo/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/IntercomExpo/assets/splash.png -------------------------------------------------------------------------------- /sandboxes/IntercomExpo/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /sandboxes/IntercomExpo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "intercomexpo", 3 | "version": "1.0.0", 4 | "main": "node_modules/expo/AppEntry.js", 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "expo run:android", 8 | "ios": "expo run:ios", 9 | "web": "expo start --web" 10 | }, 11 | "dependencies": { 12 | "@intercom/intercom-react-native": "^7.0.1", 13 | "expo": "^52.0.37", 14 | "expo-build-properties": "~0.12.5", 15 | "expo-status-bar": "~1.12.1", 16 | "expo-system-ui": "~3.0.7", 17 | "react": "18.2.0", 18 | "react-native": "0.74.5", 19 | "react-native-mmkv-storage": "^0.9.1" 20 | }, 21 | "devDependencies": { 22 | "@babel/core": "^7.20.0" 23 | }, 24 | "private": true 25 | } 26 | -------------------------------------------------------------------------------- /sandboxes/IntercomExpo/useIntercom.js: -------------------------------------------------------------------------------- 1 | import Intercom, { 2 | Space, 3 | IntercomContent, 4 | } from '@intercom/intercom-react-native'; 5 | import { useMMKVStorage } from 'react-native-mmkv-storage'; 6 | import { storage } from './App.utils'; 7 | 8 | export function useIntercom() { 9 | const [userIdentifier, setUserIdentifier] = useMMKVStorage('id', storage, ''); 10 | 11 | const [isLoggedIn, setIsLoggedIn] = useMMKVStorage('login', storage, false); 12 | 13 | const handleLoginIdentifiedUser = async () => { 14 | setIsLoggedIn(true); 15 | await Intercom.loginUserWithUserAttributes({ 16 | email: userIdentifier, 17 | }); 18 | }; 19 | 20 | const handleLoginUnidentifiedUser = async () => { 21 | setIsLoggedIn(true); 22 | await Intercom.loginUnidentifiedUser(); 23 | }; 24 | 25 | const handleLogout = async () => { 26 | await Intercom.logout(); 27 | setIsLoggedIn(false); 28 | }; 29 | 30 | const openMessages = () => { 31 | Intercom.presentSpace(Space.messages); 32 | }; 33 | 34 | const openHelpCenter = () => { 35 | Intercom.presentSpace(Space.helpCenter); 36 | }; 37 | 38 | const openTicketsSpace = () => { 39 | Intercom.presentSpace(Space.tickets); 40 | }; 41 | 42 | const openMessenger = () => { 43 | Intercom.present(); 44 | }; 45 | 46 | const openHelpCenterCollection = (collectionIds) => { 47 | let helpCenterCollectionsContent = 48 | IntercomContent.helpCenterCollectionsWithIds(collectionIds); 49 | Intercom.presentContent(helpCenterCollectionsContent); 50 | }; 51 | 52 | const openConversation = (conversationId) => { 53 | let conversationContent = 54 | IntercomContent.conversationWithConversationId(conversationId); 55 | Intercom.presentContent(conversationContent); 56 | }; 57 | 58 | const openArticle = (articleId) => { 59 | let articleContent = IntercomContent.articleWithArticleId(articleId); 60 | Intercom.presentContent(articleContent); 61 | }; 62 | 63 | const openCarousel = (carouselId) => { 64 | let carouselContent = IntercomContent.carouselWithCarouselId(carouselId); 65 | Intercom.presentContent(carouselContent); 66 | }; 67 | 68 | const openSurvey = (surveyId) => { 69 | let surveyContent = IntercomContent.surveyWithSurveyId(surveyId); 70 | Intercom.presentContent(surveyContent); 71 | }; 72 | 73 | const toggleLauncher = (visibility) => { 74 | Intercom.setLauncherVisibility(visibility); 75 | }; 76 | 77 | const openMessageComposer = () => { 78 | Intercom.presentMessageComposer('initial message'); 79 | }; 80 | 81 | return { 82 | setUserIdentifier, 83 | isLoggedIn, 84 | handleLoginIdentifiedUser, 85 | handleLoginUnidentifiedUser, 86 | handleLogout, 87 | openMessages, 88 | openHelpCenter, 89 | openTicketsSpace, 90 | openMessenger, 91 | openHelpCenterCollection, 92 | openConversation, 93 | openArticle, 94 | openCarousel, 95 | openSurvey, 96 | toggleLauncher, 97 | openMessageComposer, 98 | }; 99 | } 100 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native', 4 | }; 5 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | ios/.xcode.env.local 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | .cxx/ 34 | *.keystore 35 | !debug.keystore 36 | 37 | # node.js 38 | # 39 | node_modules/ 40 | npm-debug.log 41 | yarn-error.log 42 | 43 | # fastlane 44 | # 45 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 46 | # screenshots whenever they are needed. 47 | # For more information about the recommended setup visit: 48 | # https://docs.fastlane.tools/best-practices/source-control/ 49 | 50 | **/fastlane/report.xml 51 | **/fastlane/Preview.html 52 | **/fastlane/screenshots 53 | **/fastlane/test_output 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # Ruby / CocoaPods 59 | /ios/Pods/ 60 | /vendor/bundle/ 61 | 62 | # Temporary files created by Metro to check the health of the file watcher 63 | .metro-health-check* 64 | 65 | # testing 66 | /coverage 67 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'avoid', 3 | bracketSameLine: true, 4 | bracketSpacing: false, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | }; 8 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/App.styles.ts: -------------------------------------------------------------------------------- 1 | import {StyleSheet} from 'react-native'; 2 | 3 | export const styles = StyleSheet.create({ 4 | screenWrapper: { 5 | flex: 1, 6 | alignItems: 'center', 7 | justifyContent: 'center', 8 | }, 9 | title: { 10 | marginTop: 25, 11 | fontWeight: 'bold', 12 | fontSize: 20, 13 | }, 14 | wrapper: { 15 | width: '50%', 16 | }, 17 | input: { 18 | borderWidth: 1, 19 | borderColor: 'rgba(0,0,80,0.2)', 20 | backgroundColor: '#f3f8ff', 21 | paddingVertical: 10, 22 | fontSize: 18, 23 | marginBottom: 10, 24 | }, 25 | button: { 26 | backgroundColor: '#7284c5', 27 | paddingVertical: 13, 28 | alignItems: 'center', 29 | }, 30 | buttonText: { 31 | color: '#fff', 32 | }, 33 | divider: { 34 | marginVertical: 18, 35 | borderWidth: 0.5, 36 | borderColor: '#5757ca', 37 | }, 38 | }); 39 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {NavigationContainer} from '@react-navigation/native'; 3 | import {HomeScreen} from './HomeScreen.tsx'; 4 | import {SettingsScreen} from './SettingsScreen.tsx'; 5 | import {SafeAreaProvider} from 'react-native-safe-area-context'; 6 | import {createNativeStackNavigator} from '@react-navigation/native-stack'; 7 | 8 | const Stack = createNativeStackNavigator(); 9 | 10 | export default function App() { 11 | return ( 12 | 13 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/App.utils.ts: -------------------------------------------------------------------------------- 1 | import {MMKVLoader} from 'react-native-mmkv-storage'; 2 | 3 | export const storage = new MMKVLoader().initialize(); 4 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby ">= 2.6.10" 5 | 6 | # Cocoapods 1.15 introduced a bug which break the build. We will remove the upper 7 | # bound in the template on Cocoapods with next React Native release. 8 | gem 'cocoapods', '>= 1.13', '< 1.15' 9 | gem 'activesupport', '>= 6.1.7.5', '< 7.1.0' 10 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.7) 5 | base64 6 | nkf 7 | rexml 8 | activesupport (6.1.7.7) 9 | concurrent-ruby (~> 1.0, >= 1.0.2) 10 | i18n (>= 1.6, < 2) 11 | minitest (>= 5.1) 12 | tzinfo (~> 2.0) 13 | zeitwerk (~> 2.3) 14 | addressable (2.8.6) 15 | public_suffix (>= 2.0.2, < 6.0) 16 | algoliasearch (1.27.5) 17 | httpclient (~> 2.8, >= 2.8.3) 18 | json (>= 1.5.1) 19 | atomos (0.1.3) 20 | base64 (0.2.0) 21 | claide (1.1.0) 22 | cocoapods (1.14.3) 23 | addressable (~> 2.8) 24 | claide (>= 1.0.2, < 2.0) 25 | cocoapods-core (= 1.14.3) 26 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 27 | cocoapods-downloader (>= 2.1, < 3.0) 28 | cocoapods-plugins (>= 1.0.0, < 2.0) 29 | cocoapods-search (>= 1.0.0, < 2.0) 30 | cocoapods-trunk (>= 1.6.0, < 2.0) 31 | cocoapods-try (>= 1.1.0, < 2.0) 32 | colored2 (~> 3.1) 33 | escape (~> 0.0.4) 34 | fourflusher (>= 2.3.0, < 3.0) 35 | gh_inspector (~> 1.0) 36 | molinillo (~> 0.8.0) 37 | nap (~> 1.0) 38 | ruby-macho (>= 2.3.0, < 3.0) 39 | xcodeproj (>= 1.23.0, < 2.0) 40 | cocoapods-core (1.14.3) 41 | activesupport (>= 5.0, < 8) 42 | addressable (~> 2.8) 43 | algoliasearch (~> 1.0) 44 | concurrent-ruby (~> 1.1) 45 | fuzzy_match (~> 2.0.4) 46 | nap (~> 1.0) 47 | netrc (~> 0.11) 48 | public_suffix (~> 4.0) 49 | typhoeus (~> 1.0) 50 | cocoapods-deintegrate (1.0.5) 51 | cocoapods-downloader (2.1) 52 | cocoapods-plugins (1.0.0) 53 | nap 54 | cocoapods-search (1.0.1) 55 | cocoapods-trunk (1.6.0) 56 | nap (>= 0.8, < 2.0) 57 | netrc (~> 0.11) 58 | cocoapods-try (1.2.0) 59 | colored2 (3.1.2) 60 | concurrent-ruby (1.2.3) 61 | escape (0.0.4) 62 | ethon (0.16.0) 63 | ffi (>= 1.15.0) 64 | ffi (1.16.3) 65 | fourflusher (2.3.1) 66 | fuzzy_match (2.0.4) 67 | gh_inspector (1.1.3) 68 | httpclient (2.8.3) 69 | i18n (1.14.4) 70 | concurrent-ruby (~> 1.0) 71 | json (2.7.2) 72 | minitest (5.22.3) 73 | molinillo (0.8.0) 74 | nanaimo (0.3.0) 75 | nap (1.1.0) 76 | netrc (0.11.0) 77 | nkf (0.2.0) 78 | public_suffix (4.0.7) 79 | rexml (3.3.9) 80 | ruby-macho (2.5.1) 81 | typhoeus (1.4.1) 82 | ethon (>= 0.9.0) 83 | tzinfo (2.0.6) 84 | concurrent-ruby (~> 1.0) 85 | xcodeproj (1.25.1) 86 | CFPropertyList (>= 2.3.3, < 4.0) 87 | atomos (~> 0.1.3) 88 | claide (>= 1.0.2, < 2.0) 89 | colored2 (~> 3.1) 90 | nanaimo (~> 0.3.0) 91 | rexml (>= 3.3.6, < 4.0) 92 | zeitwerk (2.6.13) 93 | 94 | PLATFORMS 95 | ruby 96 | 97 | DEPENDENCIES 98 | activesupport (>= 6.1.7.5, < 7.1.0) 99 | cocoapods (>= 1.13, < 1.15) 100 | 101 | RUBY VERSION 102 | ruby 2.6.10p210 103 | 104 | BUNDLED WITH 105 | 2.1.4 106 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/HomeScreen.tsx: -------------------------------------------------------------------------------- 1 | import React, {useEffect} from 'react'; 2 | import {AppState, Text, TextInput, TouchableOpacity, View} from 'react-native'; 3 | import Intercom, {Visibility} from '@intercom/intercom-react-native'; 4 | import {requestNotifications} from 'react-native-permissions'; 5 | import {useIntercom} from './useIntercom.tsx'; 6 | import {styles} from './App.styles.ts'; 7 | 8 | export function HomeScreen(): React.JSX.Element { 9 | useEffect(() => { 10 | const subscription = AppState.addEventListener( 11 | 'change', 12 | nextStatus => nextStatus === 'active' && Intercom.handlePushMessage(), 13 | ); 14 | return subscription.remove; 15 | }, []); 16 | 17 | useEffect(() => { 18 | (async () => { 19 | // Request permissions 20 | await requestNotifications([ 21 | 'alert', 22 | 'sound', 23 | 'criticalAlert', 24 | 'badge', 25 | 'provisional', 26 | 'carPlay', 27 | 'providesAppSettings', 28 | ]); 29 | 30 | await Intercom.setLauncherVisibility(Visibility.VISIBLE); 31 | })(); 32 | }, []); 33 | 34 | const { 35 | handleLoginIdentifiedUser, 36 | handleLoginUnidentifiedUser, 37 | handleLogout, 38 | setUserIdentifier, 39 | isLoggedIn, 40 | } = useIntercom(); 41 | 42 | return ( 43 | 44 | Push Notifications Sandbox 45 | 46 | {!isLoggedIn ? ( 47 | <> 48 | 49 | 52 | Login Identified User 53 | 54 | 55 | 56 | 57 | 60 | Login Unidentified User 61 | 62 | 63 | ) : ( 64 | 65 | Logout 66 | 67 | )} 68 | 69 | 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/SettingsScreen.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Text} from 'react-native'; 3 | import {styles} from './App.styles.ts'; 4 | 5 | export function SettingsScreen(): React.JSX.Element { 6 | return Settings Screen; 7 | } 8 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | apply plugin: "org.jetbrains.kotlin.android" 3 | apply plugin: "com.facebook.react" 4 | 5 | /** 6 | * This is the configuration block to customize your React Native Android app. 7 | * By default you don't need to apply any configuration, just uncomment the lines you need. 8 | */ 9 | react { 10 | /* Folders */ 11 | // The root of your project, i.e. where "package.json" lives. Default is '..' 12 | // root = file("../") 13 | // The folder where the react-native NPM package is. Default is ../node_modules/react-native 14 | // reactNativeDir = file("../node_modules/react-native") 15 | // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen 16 | // codegenDir = file("../node_modules/@react-native/codegen") 17 | // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js 18 | // cliFile = file("../node_modules/react-native/cli.js") 19 | 20 | /* Variants */ 21 | // The list of variants to that are debuggable. For those we're going to 22 | // skip the bundling of the JS bundle and the assets. By default is just 'debug'. 23 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. 24 | // debuggableVariants = ["liteDebug", "prodDebug"] 25 | 26 | /* Bundling */ 27 | // A list containing the node command and its flags. Default is just 'node'. 28 | // nodeExecutableAndArgs = ["node"] 29 | // 30 | // The command to run when bundling. By default is 'bundle' 31 | // bundleCommand = "ram-bundle" 32 | // 33 | // The path to the CLI configuration file. Default is empty. 34 | // bundleConfig = file(../rn-cli.config.js) 35 | // 36 | // The name of the generated asset file containing your JS bundle 37 | // bundleAssetName = "MyApplication.android.bundle" 38 | // 39 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' 40 | // entryFile = file("../js/MyApplication.android.js") 41 | // 42 | // A list of extra flags to pass to the 'bundle' commands. 43 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle 44 | // extraPackagerArgs = [] 45 | 46 | /* Hermes Commands */ 47 | // The hermes compiler command to run. By default it is 'hermesc' 48 | // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" 49 | // 50 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" 51 | // hermesFlags = ["-O", "-output-source-map"] 52 | } 53 | 54 | /** 55 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode. 56 | */ 57 | def enableProguardInReleaseBuilds = false 58 | 59 | /** 60 | * The preferred build flavor of JavaScriptCore (JSC) 61 | * 62 | * For example, to use the international variant, you can use: 63 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 64 | * 65 | * The international variant includes ICU i18n library and necessary data 66 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 67 | * give correct results when using with locales other than en-US. Note that 68 | * this variant is about 6MiB larger per architecture than default. 69 | */ 70 | def jscFlavor = 'org.webkit:android-jsc:+' 71 | 72 | android { 73 | ndkVersion rootProject.ext.ndkVersion 74 | buildToolsVersion rootProject.ext.buildToolsVersion 75 | compileSdk rootProject.ext.compileSdkVersion 76 | 77 | namespace "com.example.sample" 78 | defaultConfig { 79 | applicationId "com.example.sample" 80 | minSdkVersion rootProject.ext.minSdkVersion 81 | targetSdkVersion rootProject.ext.targetSdkVersion 82 | versionCode 1 83 | versionName "1.0" 84 | } 85 | signingConfigs { 86 | debug { 87 | storeFile file('debug.keystore') 88 | storePassword 'android' 89 | keyAlias 'androiddebugkey' 90 | keyPassword 'android' 91 | } 92 | } 93 | buildTypes { 94 | debug { 95 | signingConfig signingConfigs.debug 96 | } 97 | release { 98 | // Caution! In production, you need to generate your own keystore file. 99 | // see https://reactnative.dev/docs/signed-apk-android. 100 | signingConfig signingConfigs.debug 101 | minifyEnabled enableProguardInReleaseBuilds 102 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 103 | } 104 | } 105 | } 106 | 107 | dependencies { 108 | // The version of react-native is set by the React Native Gradle Plugin 109 | implementation("com.facebook.react:react-android") 110 | 111 | if (hermesEnabled.toBoolean()) { 112 | implementation("com.facebook.react:hermes-android") 113 | } else { 114 | implementation jscFlavor 115 | } 116 | } 117 | 118 | apply plugin: 'com.google.gms.google-services' 119 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 120 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/NotificationsSandbox/android/app/debug.keystore -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/java/com/example/sample/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.sample 2 | 3 | import android.os.Bundle 4 | import android.content.Intent 5 | 6 | import com.facebook.react.ReactActivity 7 | import com.facebook.react.ReactActivityDelegate 8 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled 9 | import com.facebook.react.defaults.DefaultReactActivityDelegate 10 | 11 | class MainActivity : ReactActivity() { 12 | 13 | override fun onCreate(savedInstanceState: Bundle?) { 14 | super.onCreate(null) 15 | } 16 | 17 | /** 18 | * Returns the name of the main component registered from JavaScript. This is used to schedule 19 | * rendering of the component. 20 | */ 21 | override fun getMainComponentName(): String = "notificationsandbox" 22 | 23 | /** 24 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] 25 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] 26 | */ 27 | override fun createReactActivityDelegate(): ReactActivityDelegate = 28 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) 29 | 30 | /** 31 | * This method is called when a new intent is received while the activity is running. 32 | * It needs to be added if your app needs to handle deep links opened through push notifications. 33 | */ 34 | override fun onNewIntent(intent: Intent) { 35 | super.onNewIntent(intent) 36 | setIntent(intent) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/java/com/example/sample/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package com.example.sample 2 | 3 | import android.app.Application 4 | import com.facebook.react.PackageList 5 | import com.facebook.react.ReactApplication 6 | import com.facebook.react.ReactHost 7 | import com.facebook.react.ReactNativeHost 8 | import com.facebook.react.ReactPackage 9 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load 10 | import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost 11 | import com.facebook.react.defaults.DefaultReactNativeHost 12 | import com.facebook.soloader.SoLoader 13 | import com.intercom.reactnative.IntercomModule 14 | 15 | class MainApplication : Application(), ReactApplication { 16 | 17 | override val reactNativeHost: ReactNativeHost = 18 | object : DefaultReactNativeHost(this) { 19 | override fun getPackages(): List = 20 | PackageList(this).packages.apply { 21 | // Packages that cannot be autolinked yet can be added manually here, for example: 22 | // add(MyReactNativePackage()) 23 | } 24 | 25 | override fun getJSMainModuleName(): String = "index" 26 | 27 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG 28 | 29 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 30 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED 31 | } 32 | 33 | override val reactHost: ReactHost 34 | get() = getDefaultReactHost(this.applicationContext, reactNativeHost) 35 | 36 | override fun onCreate() { 37 | super.onCreate() 38 | SoLoader.init(this, false) 39 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 40 | // If you opted-in for the New Architecture, we load the native entry point for this app. 41 | load() 42 | } 43 | 44 | IntercomModule.initialize(this, "apiKey", "appId"); // Add your Intercom configurations here 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 21 | 22 | 23 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/NotificationsSandbox/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | notificationsandbox 3 | 4 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | buildToolsVersion = "35.0.0" 4 | minSdkVersion = 23 5 | compileSdkVersion = 35 6 | targetSdkVersion = 35 7 | ndkVersion = "26.1.10909125" 8 | kotlinVersion = "1.9.22" 9 | } 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle") 16 | classpath("com.facebook.react:react-native-gradle-plugin") 17 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 18 | classpath("com.google.gms:google-services:4.4.1") 19 | } 20 | } 21 | 22 | apply plugin: "com.facebook.react.rootproject" 23 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Use this property to specify which architecture you want to build. 28 | # You can also override it from the CLI using 29 | # ./gradlew -PreactNativeArchitectures=x86_64 30 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 31 | 32 | # Use this property to enable support to the new architecture. 33 | # This will allow you to use TurboModules and the Fabric render in 34 | # your application. You should enable this flag either if you want 35 | # to write custom TurboModules/Fabric components OR use libraries that 36 | # are providing them. 37 | newArchEnabled=false 38 | 39 | # Use this property to enable or disable the Hermes JS engine. 40 | # If set to false, you will be using JSC instead. 41 | hermesEnabled=true 42 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-react-native/2358e15137425b4362361e3082119ceafb5e3fd9/sandboxes/NotificationsSandbox/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'notificationsandbox' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | includeBuild('../node_modules/@react-native/gradle-plugin') 5 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "notificationsandbox", 3 | "displayName": "notificationsandbox" 4 | } 5 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:@react-native/babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Resolve react_native_pods.rb with node to allow for hoisting 2 | def node_require(script) 3 | # Resolve script with node to allow for hoisting 4 | require Pod::Executable.execute_command('node', ['-p', 5 | "require.resolve( 6 | '#{script}', 7 | {paths: [process.argv[1]]}, 8 | )", __dir__]).strip 9 | end 10 | 11 | node_require('react-native/scripts/react_native_pods.rb') 12 | node_require('react-native-permissions/scripts/setup.rb') 13 | 14 | platform :ios, '15' 15 | prepare_react_native_project! 16 | 17 | # ⬇️ uncomment wanted permissions 18 | setup_permissions([ 19 | 'Notifications', 20 | ]) 21 | 22 | linkage = ENV['USE_FRAMEWORKS'] 23 | if linkage != nil 24 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green 25 | use_frameworks! :linkage => linkage.to_sym 26 | end 27 | 28 | target 'notificationsandbox' do 29 | config = use_native_modules! 30 | 31 | use_react_native!( 32 | :path => config[:reactNativePath], 33 | # An absolute path to your application root. 34 | :app_path => "#{Pod::Config.instance.installation_root}/.." 35 | ) 36 | 37 | target 'notificationsandboxTests' do 38 | inherit! :complete 39 | # Pods for testing 40 | end 41 | 42 | post_install do |installer| 43 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 44 | react_native_post_install( 45 | installer, 46 | config[:reactNativePath], 47 | :mac_catalyst_enabled => false 48 | ) 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandbox.xcodeproj/xcshareddata/xcschemes/notificationsandbox.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandbox.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandbox.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandbox/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : RCTAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandbox/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | #import 5 | 6 | #import 7 | #import 8 | 9 | 10 | @implementation AppDelegate 11 | 12 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 13 | { 14 | self.moduleName = @"notificationsandbox"; 15 | // You can add your custom initial props in the dictionary below. 16 | // They will be passed down to the ViewController used by React Native. 17 | self.initialProps = @{}; 18 | 19 | UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; 20 | [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound) 21 | completionHandler:^(BOOL granted, NSError *_Nullable error) { 22 | }]; 23 | [[UIApplication sharedApplication] registerForRemoteNotifications]; 24 | 25 | [IntercomModule initialize:@"apiKey" withAppId:@"appId"]; // Add your Intercom configurations here 26 | 27 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 28 | } 29 | 30 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 31 | { 32 | return [self getBundleURL]; 33 | } 34 | 35 | - (NSURL *)getBundleURL 36 | { 37 | #if DEBUG 38 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 39 | #else 40 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 41 | #endif 42 | } 43 | 44 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 45 | [IntercomModule setDeviceToken:deviceToken]; 46 | } 47 | 48 | - (BOOL)application:(UIApplication *)application 49 | openURL:(NSURL *)url 50 | options:(NSDictionary *)options 51 | { 52 | return [RCTLinkingManager application:application openURL:url options:options]; 53 | } 54 | 55 | - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity 56 | restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler 57 | { 58 | return [RCTLinkingManager application:application 59 | continueUserActivity:userActivity 60 | restorationHandler:restorationHandler]; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandbox/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandbox/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandbox/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | notificationsandbox 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleURLTypes 24 | 25 | 26 | CFBundleURLSchemes 27 | 28 | app 29 | 30 | 31 | 32 | CFBundleVersion 33 | $(CURRENT_PROJECT_VERSION) 34 | IntercomUniversalLinkDomains 35 | 36 | app.fake 37 | 38 | LSRequiresIPhoneOS 39 | 40 | NSAppTransportSecurity 41 | 42 | NSAllowsArbitraryLoads 43 | 44 | NSAllowsLocalNetworking 45 | 46 | 47 | NSCameraUsageDescription 48 | This is just a sample text to access the Camera 49 | NSLocationWhenInUseUsageDescription 50 | 51 | NSPhotoLibraryUsageDescription 52 | This is just a sample text to access the Photo Library 53 | UIBackgroundModes 54 | 55 | remote-notification 56 | 57 | UILaunchStoryboardName 58 | LaunchScreen 59 | UIRequiredDeviceCapabilities 60 | 61 | armv7 62 | 63 | UISupportedInterfaceOrientations 64 | 65 | UIInterfaceOrientationPortrait 66 | UIInterfaceOrientationLandscapeLeft 67 | UIInterfaceOrientationLandscapeRight 68 | 69 | UIViewControllerBasedStatusBarAppearance 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandbox/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandbox/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryFileTimestamp 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | C617.1 13 | 14 | 15 | 16 | NSPrivacyAccessedAPIType 17 | NSPrivacyAccessedAPICategoryUserDefaults 18 | NSPrivacyAccessedAPITypeReasons 19 | 20 | CA92.1 21 | 22 | 23 | 24 | NSPrivacyAccessedAPIType 25 | NSPrivacyAccessedAPICategorySystemBootTime 26 | NSPrivacyAccessedAPITypeReasons 27 | 28 | 35F9.1 29 | 30 | 31 | 32 | NSPrivacyCollectedDataTypes 33 | 34 | NSPrivacyTracking 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandbox/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandbox/notificationsandbox.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | 9 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandboxTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/ios/notificationsandboxTests/notificationsandboxTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface notificationsandboxTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation notificationsandboxTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction( 38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 39 | if (level >= RCTLogLevelError) { 40 | redboxError = message; 41 | } 42 | }); 43 | #endif 44 | 45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 48 | 49 | foundElement = [self findSubviewInView:vc.view 50 | matching:^BOOL(UIView *view) { 51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 52 | return YES; 53 | } 54 | return NO; 55 | }]; 56 | } 57 | 58 | #ifdef DEBUG 59 | RCTSetLogFunction(RCTDefaultLogFunction); 60 | #endif 61 | 62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'react-native', 3 | }; 4 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/metro.config.js: -------------------------------------------------------------------------------- 1 | const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); 2 | 3 | /** 4 | * Metro configuration 5 | * https://facebook.github.io/metro/docs/configuration 6 | * 7 | * @type {import('metro-config').MetroConfig} 8 | */ 9 | const config = {}; 10 | 11 | module.exports = mergeConfig(getDefaultConfig(__dirname), config); 12 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "notificationsandbox", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "lint": "eslint .", 9 | "start": "react-native start", 10 | "test": "jest", 11 | "setup:yarn": "bundle install && yarn install", 12 | "setup:npm": "bundle install && npm install", 13 | "pod": "cd ios && bundle exec pod install", 14 | "rename": "react-native-rename 'notificationsandbox' --skipGitStatusCheck" 15 | }, 16 | "dependencies": { 17 | "@intercom/intercom-react-native": "^7.1.3", 18 | "@react-navigation/native": "^6.1.17", 19 | "@react-navigation/native-stack": "^6.9.26", 20 | "react": "18.2.0", 21 | "react-native": "0.74.5", 22 | "react-native-mmkv-storage": "^0.9.1", 23 | "react-native-permissions": "^4.1.5", 24 | "react-native-safe-area-context": "^4.9.0", 25 | "react-native-screens": "^3.30.1" 26 | }, 27 | "devDependencies": { 28 | "@babel/core": "^7.20.0", 29 | "@babel/preset-env": "^7.20.0", 30 | "@babel/runtime": "^7.27.0", 31 | "@react-native/babel-preset": "0.74.83", 32 | "@react-native/eslint-config": "0.74.83", 33 | "@react-native/metro-config": "0.74.83", 34 | "@react-native/typescript-config": "0.74.83", 35 | "@types/react": "^18.2.6", 36 | "@types/react-test-renderer": "^18.0.0", 37 | "babel-jest": "^29.6.3", 38 | "eslint": "^8.19.0", 39 | "jest": "^29.6.3", 40 | "prettier": "2.8.8", 41 | "react-native-rename": "^3.2.14", 42 | "react-test-renderer": "18.2.0", 43 | "typescript": "5.0.4" 44 | }, 45 | "engines": { 46 | "node": ">=18" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/payload.apns: -------------------------------------------------------------------------------- 1 | { 2 | "Simulator Target Bundle": "replace.with.your.bundle.id", 3 | "aps": { 4 | "alert": { 5 | "title": "Testing push notifications", 6 | "body": "Local notifications are working" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/payload.json: -------------------------------------------------------------------------------- 1 | { 2 | "aps": { 3 | "alert": { 4 | "title": "Testing push notifications", 5 | "body": "Local notifications are working" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@react-native/typescript-config/tsconfig.json", 3 | } 4 | -------------------------------------------------------------------------------- /sandboxes/NotificationsSandbox/useIntercom.tsx: -------------------------------------------------------------------------------- 1 | import Intercom from '@intercom/intercom-react-native'; 2 | import {useMMKVStorage} from 'react-native-mmkv-storage'; 3 | import {storage} from './App.utils'; 4 | 5 | export function useIntercom() { 6 | const [userIdentifier, setUserIdentifier] = useMMKVStorage( 7 | 'id', 8 | storage, 9 | '', 10 | ); 11 | const [isLoggedIn, setIsLoggedIn] = useMMKVStorage( 12 | 'login', 13 | storage, 14 | false, 15 | ); 16 | 17 | const handleLoginIdentifiedUser = async () => { 18 | setIsLoggedIn(true); 19 | await Intercom.loginUserWithUserAttributes({ 20 | email: userIdentifier, 21 | }); 22 | }; 23 | 24 | const handleLoginUnidentifiedUser = async () => { 25 | setIsLoggedIn(true); 26 | await Intercom.loginUnidentifiedUser(); 27 | }; 28 | 29 | const handleLogout = async () => { 30 | await Intercom.logout(); 31 | setIsLoggedIn(false); 32 | }; 33 | 34 | return { 35 | setUserIdentifier, 36 | isLoggedIn, 37 | handleLoginIdentifiedUser, 38 | handleLoginUnidentifiedUser, 39 | handleLogout, 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /script/setup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Functions 5 | # 6 | function log() { 7 | echo "\n" 8 | echo "=======================================" 9 | echo "$1" 10 | echo "=======================================" 11 | } 12 | 13 | log "🏎️ Running React native setup script 🏎️" 14 | 15 | log "📱 Installing xcode tools 📱" 16 | 17 | if [ ! -f /Library/Developer/CommandLineTools/usr/lib/libxcrun.dylib ]; then 18 | echo "⚠️ Xcode CommandLineTools not found installing. Please install and rerun this script ⚠️" 19 | xcode-select --install 20 | exit 1 21 | fi 22 | echo "Xcode CommandLineTools installed 👍" 23 | 24 | if ! [ -x "$(command -v xcode-select)" ]; then 25 | echo "⚠️ You need Xcode to setup this project. Please install and rerun this script ⚠️" 26 | exit 1 27 | fi 28 | 29 | log "👀 Looking for Homebrew 👀" 30 | if ! [ -x "$(command -v brew)" ]; then 31 | echo "🍺 Installing Homebrew 🍺" 32 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 33 | echo 'export PATH=/opt/homebrew/bin:$PATH' >> ~/.bash_profile 34 | echo 'export PATH=/opt/homebrew/bin:$PATH' >> ~/.zshrc 35 | else 36 | echo "Homebrew already installed 👍" 37 | fi 38 | 39 | log "👀 Looking for rbenv 👀" 40 | if ! [ -x "$(command -v rbenv)" ]; then 41 | echo "🍺 Installing rbenv with brew 🍺" 42 | brew install rbenv ruby-build 43 | echo 'eval "$(rbenv init -)"' >> ~/.bash_profile 44 | echo 'eval "$(rbenv init -)"' >> ~/.zshrc 45 | eval "$(rbenv init -)" 46 | else 47 | echo "rbenv already installed 👍" 48 | fi 49 | 50 | rbenv install --skip-existing 51 | echo "Ruby setup complete 👍" 52 | 53 | log "👀 Looking for nvm 👀" 54 | if ! [ -x "$(command -v nvm)" ]; then 55 | echo "🍺 Installing nvm with brew 🍺" 56 | brew install nvm 57 | fi 58 | 59 | # Source nvm 60 | export NVM_DIR="$HOME/.nvm" 61 | [ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && \. "/opt/homebrew/opt/nvm/nvm.sh" 62 | 63 | nvm install 64 | echo "Node.js setup complete 👍" 65 | 66 | log "👀 Looking for yarn 👀" 67 | if ! [ -x "$(command -v yarn)" ]; then 68 | echo "🍺 Installing yarn 🍺" 69 | brew install yarn 70 | else 71 | echo "yarn already installed 👍" 72 | fi 73 | 74 | log "📟 installing dependencies 📟" 75 | yarn 76 | 77 | log "📟 installing dependencies for our example app 📟" 78 | cd example/ios 79 | pod install 80 | cd - 81 | 82 | echo "You're all set up 👍" 83 | echo "📱 Run example app on iOS using -> yarn example ios" 84 | echo "📱 Run example app on android using -> yarn example android" 85 | -------------------------------------------------------------------------------- /scripts/bootstrap.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const child_process = require('child_process'); 3 | 4 | const root = path.resolve(__dirname, '..'); 5 | const args = process.argv.slice(2); 6 | const options = { 7 | cwd: process.cwd(), 8 | env: process.env, 9 | stdio: 'inherit', 10 | encoding: 'utf-8', 11 | }; 12 | 13 | let result; 14 | 15 | if (process.cwd() !== root || args.length) { 16 | // We're not in the root of the project, or additional arguments were passed 17 | // In this case, forward the command to `yarn` 18 | result = child_process.spawnSync('yarn', args, options); 19 | } else { 20 | // If `yarn` is run without arguments, perform bootstrap 21 | result = child_process.spawnSync('yarn', ['bootstrap'], options); 22 | } 23 | 24 | process.exitCode = result.status; 25 | -------------------------------------------------------------------------------- /src/expo-plugins/@types.ts: -------------------------------------------------------------------------------- 1 | export type IntercomRegion = 'US' | 'EU' | 'AU'; 2 | 3 | export type IntercomPluginProps = { 4 | iosApiKey: string; 5 | androidApiKey: string; 6 | appId: string; 7 | intercomRegion?: IntercomRegion; 8 | }; 9 | -------------------------------------------------------------------------------- /src/expo-plugins/withPushNotifications.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type ConfigPlugin, 3 | withAppDelegate, 4 | withInfoPlist, 5 | } from '@expo/config-plugins'; 6 | import type { IntercomPluginProps } from './@types'; 7 | import { 8 | findObjcFunctionCodeBlock, 9 | insertContentsInsideObjcFunctionBlock, 10 | } from '@expo/config-plugins/build/ios/codeMod'; 11 | 12 | const appDelegate: ConfigPlugin = (_config) => 13 | withAppDelegate(_config, (config) => { 14 | const setDeviceTokenCode = '[IntercomModule setDeviceToken:deviceToken];'; 15 | 16 | let stringContents = config.modResults.contents; 17 | 18 | const didRegisterBlock = findObjcFunctionCodeBlock( 19 | stringContents, 20 | 'application didRegisterForRemoteNotificationsWithDeviceToken:' 21 | ); 22 | 23 | if (!didRegisterBlock?.code.includes(setDeviceTokenCode)) { 24 | stringContents = insertContentsInsideObjcFunctionBlock( 25 | stringContents, 26 | 'application didRegisterForRemoteNotificationsWithDeviceToken:', 27 | setDeviceTokenCode, 28 | { position: 'tailBeforeLastReturn' } 29 | ); 30 | } 31 | 32 | config.modResults.contents = stringContents; 33 | return config; 34 | }); 35 | 36 | const infoPlist: ConfigPlugin = (_config) => { 37 | const newConfig = withInfoPlist(_config, (config) => { 38 | const keys = { remoteNotification: 'remote-notification' }; 39 | 40 | if (!config.modResults.UIBackgroundModes) { 41 | config.modResults.UIBackgroundModes = []; 42 | } 43 | 44 | if ( 45 | config.modResults.UIBackgroundModes?.indexOf(keys.remoteNotification) === 46 | -1 47 | ) { 48 | config.modResults.UIBackgroundModes?.push(keys.remoteNotification); 49 | } 50 | 51 | return config; 52 | }); 53 | 54 | return newConfig; 55 | }; 56 | 57 | export const withIntercomPushNotification: ConfigPlugin = ( 58 | config, 59 | props 60 | ) => { 61 | let newConfig = config; 62 | newConfig = appDelegate(config, props); 63 | newConfig = infoPlist(config, props); 64 | return newConfig; 65 | }; 66 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "extends": "./tsconfig", 4 | "exclude": ["example", "sandboxes"] 5 | } 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./", 4 | "paths": { 5 | "@intercom/intercom-react-native": ["./src/index"], 6 | }, 7 | "types": ["node", "mocha", "@wdio/globals/types", "@wdio/mocha-framework"], 8 | "allowUnreachableCode": false, 9 | "allowUnusedLabels": false, 10 | "esModuleInterop": true, 11 | "verbatimModuleSyntax": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "jsx": "react", 14 | "lib": ["esnext"], 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "noFallthroughCasesInSwitch": true, 18 | "noImplicitReturns": true, 19 | "noImplicitUseStrict": false, 20 | "noStrictGenericChecks": false, 21 | "noUnusedLocals": true, 22 | "noUnusedParameters": true, 23 | "resolveJsonModule": true, 24 | "skipLibCheck": true, 25 | "strict": true, 26 | "target": "esnext", 27 | }, 28 | "exclude": [ 29 | "example/e2e/**", 30 | "sandboxes" 31 | ] 32 | } 33 | --------------------------------------------------------------------------------