├── .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 | 
11 |
12 | 
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 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
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 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
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 |
--------------------------------------------------------------------------------