├── .gitignore
├── .npmignore
├── .ruby-version
├── .swift-version
├── BasicExample
├── .eslintrc.js
├── .gitignore
├── .prettierrc.js
├── .watchmanconfig
├── App.tsx
├── Gemfile
├── Gemfile.lock
├── android
│ ├── app
│ │ ├── build.gradle
│ │ ├── debug.keystore
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── debug
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── basicexample
│ │ │ │ └── ReactNativeFlipper.java
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── basicexample
│ │ │ │ │ ├── MainActivity.java
│ │ │ │ │ └── MainApplication.java
│ │ │ └── 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
│ │ │ └── release
│ │ │ └── java
│ │ │ └── com
│ │ │ └── basicexample
│ │ │ └── ReactNativeFlipper.java
│ ├── 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
│ ├── BasicExample.xcodeproj
│ │ ├── project.pbxproj
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── BasicExample.xcscheme
│ ├── BasicExample.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── BasicExample
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.mm
│ │ ├── BasicExample.entitlements
│ │ ├── Images.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ ├── LaunchScreen.storyboard
│ │ └── main.m
│ ├── BasicExampleTests
│ │ ├── BasicExampleTests.m
│ │ └── Info.plist
│ ├── MobileMessagingNotificationExtension.entitlements
│ ├── NotificationExtension
│ │ ├── MobileMessagingNotificationServiceExtension.plist
│ │ └── NotificationService.swift
│ └── Podfile
├── jest.config.js
├── metro.config.js
├── package.json
├── tsconfig.json
└── yarn.lock
├── Example
├── .bundle
│ └── config
├── .eslintrc.js
├── .gitignore
├── .prettierrc.js
├── .watchmanconfig
├── App.tsx
├── Gemfile
├── README.md
├── __tests__
│ └── App.test.tsx
├── android
│ ├── app
│ │ ├── build.gradle
│ │ ├── debug.keystore
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ ├── 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
├── assets
│ ├── fonts
│ │ └── Apple Chancery.ttf
│ ├── ic_add_circle.png
│ ├── ic_back.png
│ ├── ic_download.png
│ ├── ic_send.png
│ └── paperplane.fill.png
├── babel.config.js
├── components
│ └── PrimaryButton.tsx
├── constants
│ ├── Colors.ts
│ └── MyMessageStorage.ts
├── index.js
├── ios
│ ├── .ruby-version
│ ├── .xcode.env
│ ├── Example.entitlements
│ ├── Example.xcodeproj
│ │ ├── project.pbxproj
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Example.xcscheme
│ ├── Example.xcworkspace
│ │ └── contents.xcworkspacedata
│ ├── Example
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.mm
│ │ ├── Images.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ ├── LaunchScreen.storyboard
│ │ ├── PrivacyInfo.xcprivacy
│ │ └── main.m
│ ├── ExampleTests
│ │ ├── ExampleTests.m
│ │ └── Info.plist
│ ├── MobileMessagingNotificationExtension.entitlements
│ ├── NotificationExtension
│ │ ├── MobileMessagingNotificationServiceExtension.plist
│ │ └── NotificationService.swift
│ └── Podfile
├── jest.config.js
├── metro.config.js
├── package.json
├── screens
│ ├── ChatScreen.tsx
│ ├── HomeScreen.tsx
│ ├── MultiThreadChatScreen.tsx
│ ├── PersonalizeScreen.tsx
│ ├── SubviewChatScreen.tsx
│ ├── TestDeeplinkingScreen.tsx
│ └── TestDeeplinkingScreen2.tsx
└── tsconfig.json
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── README.md
├── android
├── README.md
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── infobip-mm-proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── org
│ └── infobip
│ └── reactlibrary
│ └── mobilemessaging
│ ├── CacheManager.java
│ ├── ChatCustomization.java
│ ├── ConfigCache.java
│ ├── Configuration.java
│ ├── PermissionsRequestManager.java
│ ├── RNMMChatModule.java
│ ├── RNMMChatViewManager.java
│ ├── RNMMWebRTCUI.java
│ ├── ReactChatView.java
│ ├── ReactNativeEvent.java
│ ├── ReactNativeMobileMessagingModule.java
│ ├── ReactNativeMobileMessagingPackage.java
│ ├── Utils.java
│ └── datamappers
│ └── ReactNativeJson.java
├── babel.config.js
├── infobip-mobile-messaging-react-native-plugin.podspec
├── ios
├── MobileMessagingPlugin
│ ├── RNMMChat.swift
│ ├── RNMMChatBridge.m
│ ├── RNMMChatCustomization.swift
│ ├── RNMMChatViewManager.swift
│ ├── RNMMChatViewManagerBridge.m
│ ├── RNMMWebRTCUI.swift
│ ├── RNMMWebRTCUIBridge.m
│ ├── RNMobileMessaging.swift
│ ├── RNMobileMessagingBridge.m
│ ├── RNMobileMessagingConfiguration.swift
│ ├── RNMobileMessagingErrorExtension.swift
│ ├── RNMobileMessagingEventsManager.swift
│ ├── RNMobileMessagingStorageAdapter.swift
│ └── RNMobileMessagingUtils.swift
├── ReactNativeMobileMessaging-Bridging-Header.h
└── ReactNativeMobileMessaging.xcodeproj
│ └── project.pbxproj
├── newversion
├── package.json
├── release.sh
└── src
├── components
└── RNMMChatViewNativeComponent.js
├── index.d.ts
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # node.js
6 | #
7 | node_modules/
8 | npm-debug.log
9 | yarn-error.log
10 |
11 | # Xcode
12 | #
13 | build/
14 | *.pbxuser
15 | !default.pbxuser
16 | *.mode1v3
17 | !default.mode1v3
18 | *.mode2v3
19 | !default.mode2v3
20 | *.perspectivev3
21 | !default.perspectivev3
22 | xcuserdata
23 | *.xccheckout
24 | *.moved-aside
25 | DerivedData
26 | *.hmap
27 | *.ipa
28 | *.xcuserstate
29 | project.xcworkspace
30 |
31 | # Android/IntelliJ
32 | #
33 | build/
34 | .idea
35 | .gradle
36 | local.properties
37 | *.iml
38 |
39 | # BUCK
40 | buck-out/
41 | \.buckd/
42 | *.keystore
43 | ios/Pods
44 | Podfile.lock
45 | *.tgz
46 | package-lock.json
47 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | *.log
3 | npm-debug.log
4 |
5 | # Dependency directory
6 | node_modules
7 |
8 | # Runtime data
9 | tmp
10 |
11 | # Examples (If applicable to your project)
12 | Example
13 | BasicExample
14 |
--------------------------------------------------------------------------------
/.ruby-version:
--------------------------------------------------------------------------------
1 | 2.7.8
2 |
--------------------------------------------------------------------------------
/.swift-version:
--------------------------------------------------------------------------------
1 | 5
--------------------------------------------------------------------------------
/BasicExample/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: '@react-native',
4 | };
5 |
--------------------------------------------------------------------------------
/BasicExample/.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 |
--------------------------------------------------------------------------------
/BasicExample/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | arrowParens: 'avoid',
3 | bracketSameLine: true,
4 | bracketSpacing: false,
5 | singleQuote: true,
6 | trailingComma: 'all',
7 | };
8 |
--------------------------------------------------------------------------------
/BasicExample/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/BasicExample/App.tsx:
--------------------------------------------------------------------------------
1 | import React, {useEffect} from 'react';
2 | import {
3 | Button,
4 | EmitterSubscription,
5 | ScrollView,
6 | StyleSheet,
7 | View,
8 | } from 'react-native';
9 | import {
10 | mobileMessaging,
11 | MobileMessagingReactNative,
12 | } from 'infobip-mobile-messaging-react-native-plugin';
13 |
14 | function App(): React.JSX.Element {
15 | let subscriptions: EmitterSubscription[];
16 | subscriptions = [];
17 |
18 | useEffect(() => {
19 | mobileMessaging.supportedEvents.forEach(event => {
20 | let subscription = mobileMessaging.subscribe(event, eventData =>
21 | handleMobileMessagingEvent(eventData),
22 | );
23 | subscriptions.push(subscription);
24 | });
25 | }, [subscriptions]);
26 |
27 | useEffect(() => {
28 | return () => {
29 | subscriptions.forEach(subscription => {
30 | mobileMessaging.unsubscribe(subscription);
31 | });
32 | };
33 | }, [subscriptions]);
34 |
35 | let handleMobileMessagingEvent = (value: any) => {
36 | console.log('Event: ' + JSON.stringify(value));
37 | };
38 |
39 | mobileMessaging.init(
40 | {
41 | inAppChatEnabled: false,
42 | defaultMessageStorage: false,
43 | applicationCode: 'Your application code',
44 | ios: {
45 | notificationTypes: ['alert', 'badge', 'sound'],
46 | logging: true,
47 | },
48 | android: {
49 | // For manual integration
50 | // firebaseOptions: {
51 | // apiKey: 'apiKey',
52 | // applicationId: 'applicationId',
53 | // projectId: 'projectId',
54 | // },
55 | },
56 | },
57 | () => {
58 | console.log('MobileMessaging started');
59 | },
60 | (error: MobileMessagingReactNative.MobileMessagingError) => {
61 | console.log('MobileMessaging error: ', error);
62 | },
63 | );
64 |
65 | return (
66 |
69 |
75 |
76 |
83 |
84 | );
85 | }
86 |
87 | export default App;
88 | const styles = StyleSheet.create({
89 | container: {
90 | flex: 1,
91 | flexDirection: 'column',
92 | justifyContent: 'center',
93 | alignItems: 'center',
94 | },
95 | });
96 |
--------------------------------------------------------------------------------
/BasicExample/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 | gem 'cocoapods', '~> 1.13'
7 | gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'
8 |
--------------------------------------------------------------------------------
/BasicExample/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.6)
5 | rexml
6 | activesupport (7.0.8)
7 | concurrent-ruby (~> 1.0, >= 1.0.2)
8 | i18n (>= 1.6, < 2)
9 | minitest (>= 5.1)
10 | tzinfo (~> 2.0)
11 | addressable (2.8.5)
12 | public_suffix (>= 2.0.2, < 6.0)
13 | algoliasearch (1.27.5)
14 | httpclient (~> 2.8, >= 2.8.3)
15 | json (>= 1.5.1)
16 | atomos (0.1.3)
17 | claide (1.1.0)
18 | cocoapods (1.13.0)
19 | addressable (~> 2.8)
20 | claide (>= 1.0.2, < 2.0)
21 | cocoapods-core (= 1.13.0)
22 | cocoapods-deintegrate (>= 1.0.3, < 2.0)
23 | cocoapods-downloader (>= 1.6.0, < 2.0)
24 | cocoapods-plugins (>= 1.0.0, < 2.0)
25 | cocoapods-search (>= 1.0.0, < 2.0)
26 | cocoapods-trunk (>= 1.6.0, < 2.0)
27 | cocoapods-try (>= 1.1.0, < 2.0)
28 | colored2 (~> 3.1)
29 | escape (~> 0.0.4)
30 | fourflusher (>= 2.3.0, < 3.0)
31 | gh_inspector (~> 1.0)
32 | molinillo (~> 0.8.0)
33 | nap (~> 1.0)
34 | ruby-macho (>= 2.3.0, < 3.0)
35 | xcodeproj (>= 1.23.0, < 2.0)
36 | cocoapods-core (1.13.0)
37 | activesupport (>= 5.0, < 8)
38 | addressable (~> 2.8)
39 | algoliasearch (~> 1.0)
40 | concurrent-ruby (~> 1.1)
41 | fuzzy_match (~> 2.0.4)
42 | nap (~> 1.0)
43 | netrc (~> 0.11)
44 | public_suffix (~> 4.0)
45 | typhoeus (~> 1.0)
46 | cocoapods-deintegrate (1.0.5)
47 | cocoapods-downloader (1.6.3)
48 | cocoapods-plugins (1.0.0)
49 | nap
50 | cocoapods-search (1.0.1)
51 | cocoapods-trunk (1.6.0)
52 | nap (>= 0.8, < 2.0)
53 | netrc (~> 0.11)
54 | cocoapods-try (1.2.0)
55 | colored2 (3.1.2)
56 | concurrent-ruby (1.2.2)
57 | escape (0.0.4)
58 | ethon (0.16.0)
59 | ffi (>= 1.15.0)
60 | ffi (1.16.3)
61 | fourflusher (2.3.1)
62 | fuzzy_match (2.0.4)
63 | gh_inspector (1.1.3)
64 | httpclient (2.8.3)
65 | i18n (1.14.1)
66 | concurrent-ruby (~> 1.0)
67 | json (2.6.3)
68 | minitest (5.20.0)
69 | molinillo (0.8.0)
70 | nanaimo (0.3.0)
71 | nap (1.1.0)
72 | netrc (0.11.0)
73 | public_suffix (4.0.7)
74 | rexml (3.2.6)
75 | ruby-macho (2.5.1)
76 | typhoeus (1.4.0)
77 | ethon (>= 0.9.0)
78 | tzinfo (2.0.6)
79 | concurrent-ruby (~> 1.0)
80 | xcodeproj (1.23.0)
81 | CFPropertyList (>= 2.3.3, < 4.0)
82 | atomos (~> 0.1.3)
83 | claide (>= 1.0.2, < 2.0)
84 | colored2 (~> 3.1)
85 | nanaimo (~> 0.3.0)
86 | rexml (~> 3.2.4)
87 |
88 | PLATFORMS
89 | ruby
90 |
91 | DEPENDENCIES
92 | activesupport (>= 6.1.7.3, < 7.1.0)
93 | cocoapods (~> 1.13)
94 |
95 | RUBY VERSION
96 | ruby 2.7.5p203
97 |
98 | BUNDLED WITH
99 | 2.1.4
100 |
--------------------------------------------------------------------------------
/BasicExample/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 | apply plugin: "com.facebook.react"
3 |
4 | /**
5 | * This is the configuration block to customize your React Native Android app.
6 | * By default you don't need to apply any configuration, just uncomment the lines you need.
7 | */
8 | react {
9 | /* Folders */
10 | // The root of your project, i.e. where "package.json" lives. Default is '..'
11 | // root = file("../")
12 | // The folder where the react-native NPM package is. Default is ../node_modules/react-native
13 | // reactNativeDir = file("../node_modules/react-native")
14 | // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
15 | // codegenDir = file("../node_modules/@react-native/codegen")
16 | // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
17 | // cliFile = file("../node_modules/react-native/cli.js")
18 |
19 | /* Variants */
20 | // The list of variants to that are debuggable. For those we're going to
21 | // skip the bundling of the JS bundle and the assets. By default is just 'debug'.
22 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
23 | // debuggableVariants = ["liteDebug", "prodDebug"]
24 |
25 | /* Bundling */
26 | // A list containing the node command and its flags. Default is just 'node'.
27 | // nodeExecutableAndArgs = ["node"]
28 | //
29 | // The command to run when bundling. By default is 'bundle'
30 | // bundleCommand = "ram-bundle"
31 | //
32 | // The path to the CLI configuration file. Default is empty.
33 | // bundleConfig = file(../rn-cli.config.js)
34 | //
35 | // The name of the generated asset file containing your JS bundle
36 | // bundleAssetName = "MyApplication.android.bundle"
37 | //
38 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
39 | // entryFile = file("../js/MyApplication.android.js")
40 | //
41 | // A list of extra flags to pass to the 'bundle' commands.
42 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
43 | // extraPackagerArgs = []
44 |
45 | /* Hermes Commands */
46 | // The hermes compiler command to run. By default it is 'hermesc'
47 | // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
48 | //
49 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
50 | // hermesFlags = ["-O", "-output-source-map"]
51 | }
52 |
53 | /**
54 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
55 | */
56 | def enableProguardInReleaseBuilds = false
57 |
58 | /**
59 | * The preferred build flavor of JavaScriptCore (JSC)
60 | *
61 | * For example, to use the international variant, you can use:
62 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
63 | *
64 | * The international variant includes ICU i18n library and necessary data
65 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
66 | * give correct results when using with locales other than en-US. Note that
67 | * this variant is about 6MiB larger per architecture than default.
68 | */
69 | def jscFlavor = 'org.webkit:android-jsc:+'
70 |
71 | android {
72 | ndkVersion rootProject.ext.ndkVersion
73 |
74 | compileSdkVersion rootProject.ext.compileSdkVersion
75 |
76 | namespace "com.basicexample"
77 | defaultConfig {
78 | applicationId "com.basicexample"
79 | minSdkVersion rootProject.ext.minSdkVersion
80 | targetSdkVersion rootProject.ext.targetSdkVersion
81 | versionCode 1
82 | versionName "1.0"
83 | }
84 | signingConfigs {
85 | debug {
86 | storeFile file('debug.keystore')
87 | storePassword 'android'
88 | keyAlias 'androiddebugkey'
89 | keyPassword 'android'
90 | }
91 | }
92 | buildTypes {
93 | debug {
94 | signingConfig signingConfigs.debug
95 | }
96 | release {
97 | // Caution! In production, you need to generate your own keystore file.
98 | // see https://reactnative.dev/docs/signed-apk-android.
99 | signingConfig signingConfigs.debug
100 | minifyEnabled enableProguardInReleaseBuilds
101 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
102 | }
103 | }
104 | }
105 |
106 | dependencies {
107 | // The version of react-native is set by the React Native Gradle Plugin
108 | implementation("com.facebook.react:react-android")
109 |
110 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
111 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
112 | exclude group:'com.squareup.okhttp3', module:'okhttp'
113 | }
114 |
115 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
116 | if (hermesEnabled.toBoolean()) {
117 | implementation("com.facebook.react:hermes-android")
118 | } else {
119 | implementation jscFlavor
120 | }
121 | }
122 |
123 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
124 |
--------------------------------------------------------------------------------
/BasicExample/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/BasicExample/android/app/debug.keystore
--------------------------------------------------------------------------------
/BasicExample/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 |
--------------------------------------------------------------------------------
/BasicExample/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/BasicExample/android/app/src/debug/java/com/basicexample/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Meta Platforms, Inc. and affiliates.
3 | *
4 | *
This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.basicexample;
8 |
9 | import android.content.Context;
10 | import com.facebook.flipper.android.AndroidFlipperClient;
11 | import com.facebook.flipper.android.utils.FlipperUtils;
12 | import com.facebook.flipper.core.FlipperClient;
13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping;
17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
20 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
21 | import com.facebook.react.ReactInstanceEventListener;
22 | import com.facebook.react.ReactInstanceManager;
23 | import com.facebook.react.bridge.ReactContext;
24 | import com.facebook.react.modules.network.NetworkingModule;
25 | import okhttp3.OkHttpClient;
26 |
27 | /**
28 | * Class responsible of loading Flipper inside your React Native application. This is the debug
29 | * flavor of it. Here you can add your own plugins and customize the Flipper setup.
30 | */
31 | public class ReactNativeFlipper {
32 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
33 | if (FlipperUtils.shouldEnableFlipper(context)) {
34 | final FlipperClient client = AndroidFlipperClient.getInstance(context);
35 |
36 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
37 | client.addPlugin(new DatabasesFlipperPlugin(context));
38 | client.addPlugin(new SharedPreferencesFlipperPlugin(context));
39 | client.addPlugin(CrashReporterPlugin.getInstance());
40 |
41 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
42 | NetworkingModule.setCustomClientBuilder(
43 | new NetworkingModule.CustomClientBuilder() {
44 | @Override
45 | public void apply(OkHttpClient.Builder builder) {
46 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
47 | }
48 | });
49 | client.addPlugin(networkFlipperPlugin);
50 | client.start();
51 |
52 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
53 | // Hence we run if after all native modules have been initialized
54 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
55 | if (reactContext == null) {
56 | reactInstanceManager.addReactInstanceEventListener(
57 | new ReactInstanceEventListener() {
58 | @Override
59 | public void onReactContextInitialized(ReactContext reactContext) {
60 | reactInstanceManager.removeReactInstanceEventListener(this);
61 | reactContext.runOnNativeModulesQueueThread(
62 | new Runnable() {
63 | @Override
64 | public void run() {
65 | client.addPlugin(new FrescoFlipperPlugin());
66 | }
67 | });
68 | }
69 | });
70 | } else {
71 | client.addPlugin(new FrescoFlipperPlugin());
72 | }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/java/com/basicexample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.basicexample;
2 |
3 | import com.facebook.react.ReactActivity;
4 | import com.facebook.react.ReactActivityDelegate;
5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
6 | import com.facebook.react.defaults.DefaultReactActivityDelegate;
7 |
8 | public class MainActivity extends ReactActivity {
9 |
10 | /**
11 | * Returns the name of the main component registered from JavaScript. This is used to schedule
12 | * rendering of the component.
13 | */
14 | @Override
15 | protected String getMainComponentName() {
16 | return "BasicExample";
17 | }
18 |
19 | /**
20 | * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link
21 | * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React
22 | * (aka React 18) with two boolean flags.
23 | */
24 | @Override
25 | protected ReactActivityDelegate createReactActivityDelegate() {
26 | return new DefaultReactActivityDelegate(
27 | this,
28 | getMainComponentName(),
29 | // If you opted-in for the New Architecture, we enable the Fabric Renderer.
30 | DefaultNewArchitectureEntryPoint.getFabricEnabled());
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/java/com/basicexample/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.basicexample;
2 |
3 | import android.app.Application;
4 | import com.facebook.react.PackageList;
5 | import com.facebook.react.ReactApplication;
6 | import com.facebook.react.ReactNativeHost;
7 | import com.facebook.react.ReactPackage;
8 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
9 | import com.facebook.react.defaults.DefaultReactNativeHost;
10 | import com.facebook.soloader.SoLoader;
11 | import java.util.List;
12 |
13 | public class MainApplication extends Application implements ReactApplication {
14 |
15 | private final ReactNativeHost mReactNativeHost =
16 | new DefaultReactNativeHost(this) {
17 | @Override
18 | public boolean getUseDeveloperSupport() {
19 | return BuildConfig.DEBUG;
20 | }
21 |
22 | @Override
23 | protected List getPackages() {
24 | @SuppressWarnings("UnnecessaryLocalVariable")
25 | List packages = new PackageList(this).getPackages();
26 | // Packages that cannot be autolinked yet can be added manually here, for example:
27 | // packages.add(new MyReactNativePackage());
28 | return packages;
29 | }
30 |
31 | @Override
32 | protected String getJSMainModuleName() {
33 | return "index";
34 | }
35 |
36 | @Override
37 | protected boolean isNewArchEnabled() {
38 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
39 | }
40 |
41 | @Override
42 | protected Boolean isHermesEnabled() {
43 | return BuildConfig.IS_HERMES_ENABLED;
44 | }
45 | };
46 |
47 | @Override
48 | public ReactNativeHost getReactNativeHost() {
49 | return mReactNativeHost;
50 | }
51 |
52 | @Override
53 | public void onCreate() {
54 | super.onCreate();
55 | SoLoader.init(this, /* native exopackage */ false);
56 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
57 | // If you opted-in for the New Architecture, we load the native entry point for this app.
58 | DefaultNewArchitectureEntryPoint.load();
59 | }
60 | ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/drawable/rn_edit_text_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
21 |
22 |
23 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/BasicExample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/BasicExample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/BasicExample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/BasicExample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/BasicExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/BasicExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/BasicExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/BasicExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/BasicExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/BasicExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | BasicExample
3 |
4 |
--------------------------------------------------------------------------------
/BasicExample/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/BasicExample/android/app/src/release/java/com/basicexample/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Meta Platforms, Inc. and affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.basicexample;
8 |
9 | import android.content.Context;
10 | import com.facebook.react.ReactInstanceManager;
11 |
12 | /**
13 | * Class responsible of loading Flipper inside your React Native application. This is the release
14 | * flavor of it so it's empty as we don't want to load Flipper.
15 | */
16 | public class ReactNativeFlipper {
17 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
18 | // Do nothing as we don't want to initialize Flipper on Release.
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/BasicExample/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | buildToolsVersion = "33.0.0"
6 | minSdkVersion = 21
7 | compileSdkVersion = 33
8 | targetSdkVersion = 33
9 |
10 | // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
11 | ndkVersion = "23.1.7779620"
12 | }
13 | repositories {
14 | google()
15 | mavenCentral()
16 | }
17 | dependencies {
18 | classpath("com.android.tools.build:gradle")
19 | classpath("com.facebook.react:react-native-gradle-plugin")
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/BasicExample/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 | # Version of flipper SDK to use with React Native
28 | FLIPPER_VERSION=0.182.0
29 |
30 | # Use this property to specify which architecture you want to build.
31 | # You can also override it from the CLI using
32 | # ./gradlew -PreactNativeArchitectures=x86_64
33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
34 |
35 | # Use this property to enable support to the new architecture.
36 | # This will allow you to use TurboModules and the Fabric render in
37 | # your application. You should enable this flag either if you want
38 | # to write custom TurboModules/Fabric components OR use libraries that
39 | # are providing them.
40 | newArchEnabled=false
41 |
42 | # Use this property to enable or disable the Hermes JS engine.
43 | # If set to false, you will be using JSC instead.
44 | hermesEnabled=true
45 |
--------------------------------------------------------------------------------
/BasicExample/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/BasicExample/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/BasicExample/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip
4 | networkTimeout=10000
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/BasicExample/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 |
--------------------------------------------------------------------------------
/BasicExample/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'BasicExample'
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 |
--------------------------------------------------------------------------------
/BasicExample/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "BasicExample",
3 | "displayName": "BasicExample"
4 | }
5 |
--------------------------------------------------------------------------------
/BasicExample/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:metro-react-native-babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/BasicExample/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 |
--------------------------------------------------------------------------------
/BasicExample/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 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExample.xcodeproj/xcshareddata/xcschemes/BasicExample.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 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExample.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : RCTAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExample/AppDelegate.mm:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 |
3 | #import
4 | #import
5 |
6 | @implementation AppDelegate
7 |
8 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
9 | {
10 | self.moduleName = @"BasicExample";
11 | // You can add your custom initial props in the dictionary below.
12 | // They will be passed down to the ViewController used by React Native.
13 | self.initialProps = @{};
14 | [MobileMessagingPluginApplicationDelegate install];
15 |
16 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
17 | }
18 |
19 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
20 | {
21 | #if DEBUG
22 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
23 | #else
24 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
25 | #endif
26 | }
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExample/BasicExample.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | aps-environment
6 | development
7 | com.apple.security.application-groups
8 |
9 | group.com.infobip.mobilemessaging.reactnative.test.appGroup
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExample/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 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExample/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | BasicExample
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 | CFBundleVersion
24 | $(CURRENT_PROJECT_VERSION)
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSExceptionDomains
30 |
31 | localhost
32 |
33 | NSExceptionAllowsInsecureHTTPLoads
34 |
35 |
36 |
37 |
38 | NSLocationWhenInUseUsageDescription
39 |
40 | UIBackgroundModes
41 |
42 | processing
43 | remote-notification
44 |
45 | UILaunchStoryboardName
46 | LaunchScreen
47 | UIRequiredDeviceCapabilities
48 |
49 | armv7
50 |
51 | UISupportedInterfaceOrientations
52 |
53 | UIInterfaceOrientationPortrait
54 | UIInterfaceOrientationLandscapeLeft
55 | UIInterfaceOrientationLandscapeRight
56 |
57 | UIViewControllerBasedStatusBarAppearance
58 |
59 | com.mobilemessaging.app_group
60 | group.com.infobip.mobilemessaging.reactnative.test.appGroup
61 |
62 |
63 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExample/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExample/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 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExampleTests/BasicExampleTests.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 BasicExampleTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation BasicExampleTests
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 |
--------------------------------------------------------------------------------
/BasicExample/ios/BasicExampleTests/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 |
--------------------------------------------------------------------------------
/BasicExample/ios/MobileMessagingNotificationExtension.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.application-groups
6 |
7 | group.com.infobip.mobilemessaging.reactnative.test.appGroup
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/BasicExample/ios/NotificationExtension/MobileMessagingNotificationServiceExtension.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | MobileMessagingNotificationExtension
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | XPC!
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | NSExtension
24 |
25 | NSExtensionPointIdentifier
26 | com.apple.usernotifications.service
27 | NSExtensionPrincipalClass
28 | $(PRODUCT_MODULE_NAME).NotificationService
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/BasicExample/ios/NotificationExtension/NotificationService.swift:
--------------------------------------------------------------------------------
1 | // NotificationService.swift
2 |
3 | import UserNotifications
4 | import MobileMessaging
5 |
6 | @available(iOS 10.0, *)
7 | class NotificationService: UNNotificationServiceExtension {
8 |
9 | var contentHandler: ((UNNotificationContent) -> Void)?
10 | var originalContent: UNNotificationContent?
11 |
12 | override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
13 | self.contentHandler = contentHandler
14 | self.originalContent = request.content
15 | MobileMessagingNotificationServiceExtension.startWithApplicationCode("")
16 | MobileMessagingNotificationServiceExtension.didReceive(request, withContentHandler: contentHandler)
17 | }
18 |
19 | override func serviceExtensionTimeWillExpire() {
20 | MobileMessagingNotificationServiceExtension.serviceExtensionTimeWillExpire()
21 | if let originalContent = originalContent {
22 | contentHandler?(originalContent)
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/BasicExample/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Resolve react_native_pods.rb with node to allow for hoisting
2 | require Pod::Executable.execute_command('node', ['-p',
3 | 'require.resolve(
4 | "react-native/scripts/react_native_pods.rb",
5 | {paths: [process.argv[1]]},
6 | )', __dir__]).strip
7 |
8 | platform :ios, min_ios_version_supported
9 | prepare_react_native_project!
10 |
11 | # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
12 | # because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
13 | #
14 | # To fix this you can also exclude `react-native-flipper` using a `react-native.config.js`
15 | # ```js
16 | # module.exports = {
17 | # dependencies: {
18 | # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}),
19 | # ```
20 | flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
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 'BasicExample' do
29 | config = use_native_modules!
30 |
31 | # Flags change depending on the env values.
32 | flags = get_default_flags()
33 |
34 | use_react_native!(
35 | :path => config[:reactNativePath],
36 | # Hermes is now enabled by default. Disable by setting this flag to false.
37 | :hermes_enabled => flags[:hermes_enabled],
38 | :fabric_enabled => flags[:fabric_enabled],
39 | # Enables Flipper.
40 | #
41 | # Note that if you have use_frameworks! enabled, Flipper will not work and
42 | # you should disable the next line.
43 | :flipper_configuration => flipper_config,
44 | # An absolute path to your application root.
45 | :app_path => "#{Pod::Config.instance.installation_root}/.."
46 | )
47 |
48 | target 'MobileMessagingNotificationExtension' do
49 | inherit! :search_paths
50 | end
51 |
52 | target 'BasicExampleTests' do
53 | inherit! :complete
54 | # Pods for testing
55 | end
56 |
57 | post_install do |installer|
58 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
59 | react_native_post_install(
60 | installer,
61 | config[:reactNativePath],
62 | :mac_catalyst_enabled => false
63 | )
64 | __apply_Xcode_12_5_M1_post_install_workaround(installer)
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/BasicExample/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'react-native',
3 | };
4 |
--------------------------------------------------------------------------------
/BasicExample/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 |
--------------------------------------------------------------------------------
/BasicExample/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "BasicExample",
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 | },
12 | "dependencies": {
13 | "infobip-mobile-messaging-react-native-plugin": "^9.2.0",
14 | "react": "18.3.1",
15 | "react-native": "0.75.4"
16 | },
17 | "devDependencies": {
18 | "@babel/core": "^7.25.2",
19 | "@babel/runtime": "^7.25.0",
20 | "@babel/preset-env": "^7.25.0",
21 | "@react-native/eslint-config": "^0.72.2",
22 | "@react-native/metro-config": "^0.72.11",
23 | "@tsconfig/react-native": "^3.0.0",
24 | "@types/react": "^18.0.24",
25 | "@types/react-test-renderer": "^18.0.0",
26 | "babel-jest": "^29.6.3",
27 | "eslint": "^8.19.0",
28 | "jest": "^29.6.3",
29 | "metro-react-native-babel-preset": "0.76.8",
30 | "prettier": "^2.4.1",
31 | "react-test-renderer": "18.3.1",
32 | "typescript": "4.8.4"
33 | },
34 | "engines": {
35 | "node": ">=16"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/BasicExample/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/react-native/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/Example/.bundle/config:
--------------------------------------------------------------------------------
1 | BUNDLE_PATH: "vendor/bundle"
2 | BUNDLE_FORCE_RUBY_PLATFORM: 1
3 |
--------------------------------------------------------------------------------
/Example/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: '@react-native',
4 | };
5 |
--------------------------------------------------------------------------------
/Example/.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 | **/.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 | **/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 |
68 | # Yarn
69 | .yarn/*
70 | !.yarn/patches
71 | !.yarn/plugins
72 | !.yarn/releases
73 | !.yarn/sdks
74 | !.yarn/versions
75 |
--------------------------------------------------------------------------------
/Example/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | arrowParens: 'avoid',
3 | bracketSameLine: true,
4 | bracketSpacing: false,
5 | singleQuote: true,
6 | trailingComma: 'all',
7 | };
8 |
--------------------------------------------------------------------------------
/Example/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/Example/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 | # Exclude problematic versions of cocoapods and activesupport that causes build failures.
7 | gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1'
8 | gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0'
9 |
--------------------------------------------------------------------------------
/Example/README.md:
--------------------------------------------------------------------------------
1 | This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli).
2 |
3 | # Getting Started
4 |
5 | >**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding.
6 |
7 | ## Step 1: Start the Metro Server
8 |
9 | First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native.
10 |
11 | To start Metro, run the following command from the _root_ of your React Native project:
12 |
13 | ```bash
14 | # using npm
15 | npm start
16 |
17 | # OR using Yarn
18 | yarn start
19 | ```
20 |
21 | ## Step 2: Start your Application
22 |
23 | Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app:
24 |
25 | ### For Android
26 |
27 | ```bash
28 | # using npm
29 | npm run android
30 |
31 | # OR using Yarn
32 | yarn android
33 | ```
34 |
35 | ### For iOS
36 |
37 | ```bash
38 | # using npm
39 | npm run ios
40 |
41 | # OR using Yarn
42 | yarn ios
43 | ```
44 |
45 | If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly.
46 |
47 | This is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively.
48 |
49 | ## Step 3: Modifying your App
50 |
51 | Now that you have successfully run the app, let's modify it.
52 |
53 | 1. Open `App.tsx` in your text editor of choice and edit some lines.
54 | 2. For **Android**: Press the R key twice or select **"Reload"** from the **Developer Menu** (Ctrl + M (on Window and Linux) or Cmd ⌘ + M (on macOS)) to see your changes!
55 |
56 | For **iOS**: Hit Cmd ⌘ + R in your iOS Simulator to reload the app and see your changes!
57 |
58 | ## Congratulations! :tada:
59 |
60 | You've successfully run and modified your React Native App. :partying_face:
61 |
62 | ### Now what?
63 |
64 | - If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).
65 | - If you're curious to learn more about React Native, check out the [Introduction to React Native](https://reactnative.dev/docs/getting-started).
66 |
67 | # Troubleshooting
68 |
69 | If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
70 |
71 | # Learn More
72 |
73 | To learn more about React Native, take a look at the following resources:
74 |
75 | - [React Native Website](https://reactnative.dev) - learn more about React Native.
76 | - [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.
77 | - [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.
78 | - [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.
79 | - [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.
80 |
--------------------------------------------------------------------------------
/Example/__tests__/App.test.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 |
5 | import 'react-native';
6 | import React from 'react';
7 | import App from '../App';
8 |
9 | // Note: import explicitly to use the types shipped with jest.
10 | import {it} from '@jest/globals';
11 |
12 | // Note: test renderer must be required after react-native.
13 | import renderer from 'react-test-renderer';
14 |
15 | it('renders correctly', () => {
16 | renderer.create();
17 | });
18 |
--------------------------------------------------------------------------------
/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 |
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 | /* Autolinking */
54 | autolinkLibrariesWithApp()
55 | }
56 |
57 | /**
58 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
59 | */
60 | def enableProguardInReleaseBuilds = false
61 |
62 | /**
63 | * The preferred build flavor of JavaScriptCore (JSC)
64 | *
65 | * For example, to use the international variant, you can use:
66 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
67 | *
68 | * The international variant includes ICU i18n library and necessary data
69 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
70 | * give correct results when using with locales other than en-US. Note that
71 | * this variant is about 6MiB larger per architecture than default.
72 | */
73 | def jscFlavor = 'org.webkit:android-jsc:+'
74 |
75 | android {
76 | ndkVersion rootProject.ext.ndkVersion
77 | buildToolsVersion rootProject.ext.buildToolsVersion
78 | compileSdk rootProject.ext.compileSdkVersion
79 |
80 | namespace "com.example"
81 | defaultConfig {
82 | applicationId "com.example"
83 | minSdkVersion rootProject.ext.minSdkVersion
84 | targetSdkVersion rootProject.ext.targetSdkVersion
85 | versionCode 1
86 | versionName "1.0"
87 | }
88 | signingConfigs {
89 | debug {
90 | storeFile file('debug.keystore')
91 | storePassword 'android'
92 | keyAlias 'androiddebugkey'
93 | keyPassword 'android'
94 | }
95 | }
96 | buildTypes {
97 | debug {
98 | signingConfig signingConfigs.debug
99 | }
100 | release {
101 | // Caution! In production, you need to generate your own keystore file.
102 | // see https://reactnative.dev/docs/signed-apk-android.
103 | signingConfig signingConfigs.debug
104 | minifyEnabled enableProguardInReleaseBuilds
105 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
106 | }
107 | }
108 | }
109 |
110 | dependencies {
111 | // The version of react-native is set by the React Native Gradle Plugin
112 | implementation("com.facebook.react:react-android")
113 |
114 | if (hermesEnabled.toBoolean()) {
115 | implementation("com.facebook.react:hermes-android")
116 | } else {
117 | implementation jscFlavor
118 | }
119 | }
120 |
121 | apply plugin: 'com.google.gms.google-services'
122 |
--------------------------------------------------------------------------------
/Example/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/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 |
--------------------------------------------------------------------------------
/Example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
19 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Example/android/app/src/main/java/com/example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example
2 |
3 | import com.facebook.react.ReactActivity
4 | import com.facebook.react.ReactActivityDelegate
5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
6 | import com.facebook.react.defaults.DefaultReactActivityDelegate
7 |
8 | class MainActivity : ReactActivity() {
9 |
10 | /**
11 | * Returns the name of the main component registered from JavaScript. This is used to schedule
12 | * rendering of the component.
13 | */
14 | override fun getMainComponentName(): String = "Example"
15 |
16 | /**
17 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
18 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
19 | */
20 | override fun createReactActivityDelegate(): ReactActivityDelegate =
21 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
22 | }
23 |
--------------------------------------------------------------------------------
/Example/android/app/src/main/java/com/example/MainApplication.kt:
--------------------------------------------------------------------------------
1 | package com.example
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 |
14 | class MainApplication : Application(), ReactApplication {
15 |
16 | override val reactNativeHost: ReactNativeHost =
17 | object : DefaultReactNativeHost(this) {
18 | override fun getPackages(): List =
19 | PackageList(this).packages.apply {
20 | // Packages that cannot be autolinked yet can be added manually here, for example:
21 | // add(MyReactNativePackage())
22 | }
23 |
24 | override fun getJSMainModuleName(): String = "index"
25 |
26 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
27 |
28 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
29 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
30 | }
31 |
32 | override val reactHost: ReactHost
33 | get() = getDefaultReactHost(applicationContext, reactNativeHost)
34 |
35 | override fun onCreate() {
36 | super.onCreate()
37 | SoLoader.init(this, false)
38 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
39 | // If you opted-in for the New Architecture, we load the native entry point for this app.
40 | load()
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Example/android/app/src/main/res/drawable/rn_edit_text_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
22 |
23 |
24 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/Example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/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/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/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/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/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/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/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/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/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/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/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/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/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/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/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/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/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/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/Example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Example
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
11 |
12 |
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 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/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.24"
9 | }
10 | repositories {
11 | google()
12 | mavenCentral()
13 | mavenLocal()
14 | }
15 | dependencies {
16 | classpath("com.android.tools.build:gradle")
17 | classpath("com.facebook.react:react-native-gradle-plugin")
18 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
19 | //GMS Gradle plugin
20 | classpath 'com.google.gms:google-services:4.4.2'
21 | }
22 | }
23 |
24 | allprojects {
25 | repositories {
26 | mavenCentral()
27 | google()
28 | mavenLocal()
29 | }
30 | }
31 |
32 | apply plugin: "com.facebook.react.rootproject"
33 |
--------------------------------------------------------------------------------
/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: -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 |
25 | # Use this property to specify which architecture you want to build.
26 | # You can also override it from the CLI using
27 | # ./gradlew -PreactNativeArchitectures=x86_64
28 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
29 |
30 | # Use this property to enable support to the new architecture.
31 | # This will allow you to use TurboModules and the Fabric render in
32 | # your application. You should enable this flag either if you want
33 | # to write custom TurboModules/Fabric components OR use libraries that
34 | # are providing them.
35 | newArchEnabled=false
36 |
37 | # Use this property to enable or disable the Hermes JS engine.
38 | # If set to false, you will be using JSC instead.
39 | hermesEnabled=true
40 |
--------------------------------------------------------------------------------
/Example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/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.9-all.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 | @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. 1>&2
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
48 | echo. 1>&2
49 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
50 | echo location of your Java installation. 1>&2
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. 1>&2
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
62 | echo. 1>&2
63 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
64 | echo location of your Java installation. 1>&2
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 |
--------------------------------------------------------------------------------
/Example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
2 | plugins { id("com.facebook.react.settings") }
3 | extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
4 | rootProject.name = 'Example'
5 | include ':app'
6 | includeBuild('../node_modules/@react-native/gradle-plugin')
7 |
--------------------------------------------------------------------------------
/Example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Example",
3 | "displayName": "Example"
4 | }
5 |
--------------------------------------------------------------------------------
/Example/assets/fonts/Apple Chancery.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/Example/assets/fonts/Apple Chancery.ttf
--------------------------------------------------------------------------------
/Example/assets/ic_add_circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/Example/assets/ic_add_circle.png
--------------------------------------------------------------------------------
/Example/assets/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/Example/assets/ic_back.png
--------------------------------------------------------------------------------
/Example/assets/ic_download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/Example/assets/ic_download.png
--------------------------------------------------------------------------------
/Example/assets/ic_send.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/Example/assets/ic_send.png
--------------------------------------------------------------------------------
/Example/assets/paperplane.fill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/Example/assets/paperplane.fill.png
--------------------------------------------------------------------------------
/Example/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:@react-native/babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/Example/components/PrimaryButton.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | View,
4 | Text,
5 | Pressable,
6 | StyleSheet,
7 | GestureResponderEvent,
8 | ViewStyle,
9 | TextStyle,
10 | } from 'react-native';
11 | import Colors from '../constants/Colors';
12 |
13 | interface PrimaryButtonProps {
14 | children: React.ReactNode;
15 | onPress?: (event: GestureResponderEvent) => void;
16 | }
17 |
18 | const PrimaryButton: React.FC = ({children, onPress}) => {
19 | return (
20 |
21 |
23 | pressed
24 | ? [styles.buttonInnerContainer, styles.pressed]
25 | : styles.buttonInnerContainer
26 | }
27 | onPress={onPress}
28 | android_ripple={{color: Colors.primary600}}>
29 | {children}
30 |
31 |
32 | );
33 | };
34 |
35 | export default PrimaryButton;
36 |
37 | const styles = StyleSheet.create({
38 | buttonOuterContainer: {
39 | borderRadius: 28,
40 | margin: 4,
41 | overflow: 'hidden',
42 | } as ViewStyle,
43 |
44 | buttonInnerContainer: {
45 | backgroundColor: Colors.primary500,
46 | paddingVertical: 8,
47 | paddingHorizontal: 16,
48 | } as ViewStyle,
49 |
50 | buttonText: {
51 | color: Colors.tintWhite,
52 | textAlign: 'center',
53 | } as TextStyle,
54 |
55 | pressed: {
56 | opacity: 0.75,
57 | } as ViewStyle,
58 | });
59 |
--------------------------------------------------------------------------------
/Example/constants/Colors.ts:
--------------------------------------------------------------------------------
1 | const Colors = {
2 | primary500: '#ea6e39',
3 | primary600: '#8f3502',
4 | primaryGray: '#373a3b',
5 | tintWhite: '#F1F1F1',
6 | } as const;
7 |
8 | export default Colors;
9 |
--------------------------------------------------------------------------------
/Example/constants/MyMessageStorage.ts:
--------------------------------------------------------------------------------
1 | import AsyncStorage from '@react-native-async-storage/async-storage';
2 | import type {Message, CustomMessageStorage} from 'infobip-mobile-messaging-react-native-plugin';
3 |
4 | const MyMessageStorage: CustomMessageStorage = {
5 | save(messages: Message[]) {
6 | for (const message of messages) {
7 | AsyncStorage.setItem(message.messageId, JSON.stringify(message));
8 | }
9 | console.log('[CustomStorage] Saving messages: ' + JSON.stringify(messages));
10 | },
11 |
12 | async find(messageId: string, callback: (message: Message | null) => void): Promise {
13 | console.log('[CustomStorage] Find message: ' + messageId);
14 | try {
15 | const messageString = await AsyncStorage.getItem(messageId);
16 | if (messageString) {
17 | console.log('[CustomStorage] Found message: ' + messageString);
18 | const message: Message = JSON.parse(messageString);
19 | callback(message);
20 | } else {
21 | console.log('[CustomStorage] Message not found');
22 | callback(null);
23 | }
24 | } catch (error) {
25 | console.log('[CustomStorage] Error finding message: ', error);
26 | callback(null);
27 | }
28 | },
29 |
30 | findAll(callback: (messages: Message[]) => void): void {
31 | console.log('[CustomStorage] Find all');
32 | this.getAllMessages((messages: Message[]) => {
33 | console.log('[CustomStorage] Find all messages result: ', messages);
34 | callback(messages);
35 | });
36 | },
37 |
38 | start() {
39 | console.log('[CustomStorage] Start');
40 | },
41 |
42 | stop() {
43 | console.log('[CustomStorage] Stop');
44 | },
45 |
46 | getAllMessages(callback: (messages: Message[]) => void): void {
47 | AsyncStorage.getAllKeys()
48 | .then((keys) => {
49 | console.log('[CustomStorage] All Keys: ', keys);
50 | return AsyncStorage.multiGet(keys);
51 | })
52 | .then((stores) => {
53 | console.log('[CustomStorage] All Values: ', stores);
54 | const messages: Message[] = stores
55 | .map(([_, value]) => {
56 | if (value) {
57 | return JSON.parse(value) as Message;
58 | }
59 | return null;
60 | })
61 | .filter((message): message is Message => message !== null);
62 | callback(messages);
63 | })
64 | .catch((error) => {
65 | console.log('[CustomStorage] Error: ', error);
66 | callback([]);
67 | });
68 | },
69 | };
70 |
71 | export default MyMessageStorage;
72 |
--------------------------------------------------------------------------------
/Example/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 |
--------------------------------------------------------------------------------
/Example/ios/.ruby-version:
--------------------------------------------------------------------------------
1 | 2.7.8
2 |
--------------------------------------------------------------------------------
/Example/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 |
--------------------------------------------------------------------------------
/Example/ios/Example.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.application-groups
6 |
7 | group.com.infobip.mobilemessaging.reactnative
8 |
9 | aps-environment
10 | development
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example.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 |
--------------------------------------------------------------------------------
/Example/ios/Example.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/ios/Example/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : RCTAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/Example/ios/Example/AppDelegate.mm:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 |
3 | #import
4 | #import
5 |
6 | @implementation AppDelegate
7 |
8 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
9 | {
10 | [MobileMessagingPluginApplicationDelegate install];
11 |
12 | self.moduleName = @"Example";
13 | // You can add your custom initial props in the dictionary below.
14 | // They will be passed down to the ViewController used by React Native.
15 | self.initialProps = @{};
16 |
17 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
18 | }
19 |
20 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
21 | {
22 | return [self bundleURL];
23 | }
24 |
25 | - (NSURL *)bundleURL
26 | {
27 | #if DEBUG
28 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
29 | #else
30 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
31 | #endif
32 | }
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/Example/ios/Example/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 |
--------------------------------------------------------------------------------
/Example/ios/Example/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/ios/Example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | 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 | $(MARKETING_VERSION)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(CURRENT_PROJECT_VERSION)
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 |
30 | NSAllowsArbitraryLoads
31 |
32 | NSAllowsLocalNetworking
33 |
34 |
35 | NSLocationWhenInUseUsageDescription
36 |
37 | UILaunchStoryboardName
38 | LaunchScreen
39 | UIRequiredDeviceCapabilities
40 |
41 | arm64
42 |
43 | UISupportedInterfaceOrientations
44 |
45 | UIInterfaceOrientationPortrait
46 | UIInterfaceOrientationLandscapeLeft
47 | UIInterfaceOrientationLandscapeRight
48 |
49 | UIViewControllerBasedStatusBarAppearance
50 |
51 | com.mobilemessaging.app_group
52 | group.com.infobip.mobilemessaging.reactnative
53 | UIBackgroundModes
54 |
55 | remote-notification
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Example/ios/Example/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Example/ios/Example/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyAccessedAPITypes
6 |
7 |
8 | NSPrivacyAccessedAPIType
9 | NSPrivacyAccessedAPICategoryUserDefaults
10 | NSPrivacyAccessedAPITypeReasons
11 |
12 | CA92.1
13 | 1C8F.1
14 |
15 |
16 |
17 | NSPrivacyAccessedAPIType
18 | NSPrivacyAccessedAPICategoryFileTimestamp
19 | NSPrivacyAccessedAPITypeReasons
20 |
21 | C617.1
22 |
23 |
24 |
25 | NSPrivacyAccessedAPIType
26 | NSPrivacyAccessedAPICategorySystemBootTime
27 | NSPrivacyAccessedAPITypeReasons
28 |
29 | 35F9.1
30 |
31 |
32 |
33 | NSPrivacyCollectedDataTypes
34 |
35 | NSPrivacyTracking
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Example/ios/Example/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 |
--------------------------------------------------------------------------------
/Example/ios/ExampleTests/ExampleTests.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 ExampleTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation ExampleTests
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 |
--------------------------------------------------------------------------------
/Example/ios/ExampleTests/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 |
--------------------------------------------------------------------------------
/Example/ios/MobileMessagingNotificationExtension.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.application-groups
6 |
7 | group.com.infobip.mobilemessaging.reactnative
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/ios/NotificationExtension/MobileMessagingNotificationServiceExtension.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | MobileMessagingNotificationExtension
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | XPC!
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | NSExtension
24 |
25 | NSExtensionPointIdentifier
26 | com.apple.usernotifications.service
27 | NSExtensionPrincipalClass
28 | $(PRODUCT_MODULE_NAME).NotificationService
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Example/ios/NotificationExtension/NotificationService.swift:
--------------------------------------------------------------------------------
1 | // NotificationService.swift
2 |
3 | import UserNotifications
4 | import MobileMessaging
5 |
6 | @available(iOS 10.0, *)
7 | class NotificationService: UNNotificationServiceExtension {
8 |
9 | var contentHandler: ((UNNotificationContent) -> Void)?
10 | var originalContent: UNNotificationContent?
11 |
12 | override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
13 | self.contentHandler = contentHandler
14 | self.originalContent = request.content
15 |
16 | // Check if notification is from Infobip
17 | if MM_MTMessage.isCorrectPayload(request.content.userInfo) {
18 | MobileMessagingNotificationServiceExtension.startWithApplicationCode("Your application code")
19 | MobileMessagingNotificationServiceExtension.didReceive(request, withContentHandler: contentHandler)
20 | } else {
21 | // Pass through non-Infobip notifications
22 | contentHandler(request.content)
23 | }
24 | }
25 |
26 | override func serviceExtensionTimeWillExpire() {
27 | MobileMessagingNotificationServiceExtension.serviceExtensionTimeWillExpire()
28 | if let originalContent = originalContent {
29 | contentHandler?(originalContent)
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Example/ios/Podfile:
--------------------------------------------------------------------------------
1 |
2 | # Resolve react_native_pods.rb with node to allow for hoisting
3 | require Pod::Executable.execute_command('node', ['-p',
4 | 'require.resolve(
5 | "react-native/scripts/react_native_pods.rb",
6 | {paths: [process.argv[1]]},
7 | )', __dir__]).strip
8 |
9 | platform :ios, '15.1'
10 | prepare_react_native_project!
11 |
12 | linkage = ENV['USE_FRAMEWORKS']
13 | if linkage != nil
14 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
15 | use_frameworks! :linkage => linkage.to_sym
16 | end
17 |
18 | target 'Example' do
19 | config = use_native_modules!
20 |
21 | use_react_native!(
22 | :path => config[:reactNativePath],
23 | # An absolute path to your application root.
24 | :app_path => "#{Pod::Config.instance.installation_root}/.."
25 | )
26 |
27 | target 'ExampleTests' do
28 | inherit! :complete
29 | # Pods for testing
30 | end
31 |
32 | target 'MobileMessagingNotificationExtension' do
33 | inherit! :search_paths
34 | end
35 |
36 | post_install do |installer|
37 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
38 | react_native_post_install(
39 | installer,
40 | config[:reactNativePath],
41 | :mac_catalyst_enabled => false,
42 | # :ccache_enabled => true
43 | )
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/Example/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'react-native',
3 | };
4 |
--------------------------------------------------------------------------------
/Example/metro.config.js:
--------------------------------------------------------------------------------
1 | const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
2 |
3 | /**
4 | * Metro configuration
5 | * https://reactnative.dev/docs/metro
6 | *
7 | * @type {import('metro-config').MetroConfig}
8 | */
9 | const config = {};
10 |
11 | module.exports = mergeConfig(getDefaultConfig(__dirname), config);
12 |
--------------------------------------------------------------------------------
/Example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
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 | },
12 | "dependencies": {
13 | "@react-native-async-storage/async-storage": "^2.1.0",
14 | "@react-navigation/native": "^7.0.14",
15 | "@react-navigation/native-stack": "^7.2.0",
16 | "@react-navigation/stack": "^7.1.0",
17 | "infobip-mobile-messaging-react-native-plugin": "13.0.1",
18 | "react": "18.3.1",
19 | "react-native": "0.75.4",
20 | "react-native-safe-area-context": "^5.0.0",
21 | "react-native-screens": "^4.3.0",
22 | "react-native-url-polyfill": "^2.0.0"
23 | },
24 | "devDependencies": {
25 | "@babel/core": "^7.20.0",
26 | "@babel/preset-env": "^7.20.0",
27 | "@babel/runtime": "^7.20.0",
28 | "@react-native/babel-preset": "0.75.4",
29 | "@react-native/eslint-config": "0.75.4",
30 | "@react-native/metro-config": "0.75.4",
31 | "@react-native/typescript-config": "0.75.4",
32 | "@types/react": "^18.2.6",
33 | "@types/react-test-renderer": "^18.0.0",
34 | "babel-jest": "^29.6.3",
35 | "eslint": "^8.19.0",
36 | "jest": "^29.6.3",
37 | "prettier": "2.8.8",
38 | "react-test-renderer": "18.3.1",
39 | "typescript": "5.0.4"
40 | },
41 | "engines": {
42 | "node": ">=18"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Example/screens/ChatScreen.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Example of in-app Chat screen as React Component
3 | */
4 |
5 | import React from 'react';
6 | import {ChatView} from 'infobip-mobile-messaging-react-native-plugin';
7 | import Colors from '../constants/Colors';
8 |
9 | const ChatScreen: React.FC = () => {
10 | return ;
11 | };
12 |
13 | export default ChatScreen;
14 |
--------------------------------------------------------------------------------
/Example/screens/MultiThreadChatScreen.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Example of subview multithread in-app chat screen as React Component
3 | */
4 |
5 | import React, {useState, useEffect} from 'react';
6 | import {ChatView} from 'infobip-mobile-messaging-react-native-plugin';
7 | import {View, Text, KeyboardAvoidingView, SafeAreaView} from 'react-native';
8 | import Colors from '../constants/Colors';
9 | import PrimaryButton from '../components/PrimaryButton';
10 | import {mobileMessaging} from 'infobip-mobile-messaging-react-native-plugin';
11 | import {NavigationContainer, NavigationProp} from '@react-navigation/native';
12 |
13 | interface MultiThreadChatScreenProps {
14 | navigation: NavigationProp;
15 | }
16 |
17 | const MultiThreadChatScreen: React.FC = ({
18 | navigation,
19 | }) => {
20 | const [showButton, setShowButton] = useState(false);
21 |
22 | useEffect(() => {
23 | const subscription = mobileMessaging.subscribe(
24 | 'inAppChat.viewStateChanged',
25 | handleViewStateChangeEvent,
26 | );
27 |
28 | return () => {
29 | mobileMessaging.unsubscribe(subscription);
30 | };
31 | }, []);
32 |
33 | const handleViewStateChangeEvent = (value: any) => {
34 | if (typeof value !== 'undefined' && value != null) {
35 | const view = String(value).split(',').pop()?.trim();
36 | console.log('Chat view changed to: ' + view);
37 | /*
38 | Possible views: LOADING, THREAD_LIST, LOADING_THREAD, THREAD, CLOSED_THREAD, SINGLE_MODE_THREAD, UNKNOWN
39 | */
40 | const isNestedDestination =
41 | view === 'THREAD' ||
42 | view === 'LOADING_THREAD' ||
43 | view === 'CLOSED_THREAD';
44 | setShowButton(isNestedDestination);
45 | navigation.setOptions({headerShown: !isNestedDestination});
46 | }
47 | };
48 |
49 | const goBackToList = () => {
50 | mobileMessaging.showThreadsList();
51 | };
52 |
53 | return (
54 |
55 | {showButton && (
56 | Show Chat List
57 | )}
58 |
59 |
60 | );
61 | };
62 |
63 | export default MultiThreadChatScreen;
64 |
--------------------------------------------------------------------------------
/Example/screens/SubviewChatScreen.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Example of subview in-app chat screen as React Component
3 | */
4 |
5 | import React from 'react';
6 | import {ChatView} from 'infobip-mobile-messaging-react-native-plugin';
7 | import {View, Text, KeyboardAvoidingView, Platform} from 'react-native';
8 | import Colors from '../constants/Colors';
9 |
10 | const SubviewChatScreen: React.FC = () => {
11 | return (
12 |
15 |
16 | Some Title Above 1
17 | Some Title Above 2
18 | Some Title Above 3
19 |
20 |
21 | Some Title Below 5555
22 |
23 |
24 |
25 | );
26 | };
27 |
28 | export default SubviewChatScreen;
29 |
--------------------------------------------------------------------------------
/Example/screens/TestDeeplinkingScreen.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {StyleSheet, Text, View} from 'react-native';
3 | import Colors from "../constants/Colors.ts";
4 |
5 | const TestDeeplinkingScreen: React.FC = () => {
6 | return (
7 |
8 |
9 | This screen was opened by the deeplink
10 |
11 |
12 | );
13 | };
14 |
15 | const styles = StyleSheet.create({
16 | infoText: {
17 | margin: 5,
18 | fontSize: 20,
19 | fontWeight: 'bold',
20 | textAlign: 'center',
21 | lineHeight: 40,
22 | color: Colors.primaryGray,
23 | },
24 | infoView: {
25 | flex: 1,
26 | alignItems: 'center',
27 | justifyContent: 'center',
28 | },
29 | });
30 |
31 | export default TestDeeplinkingScreen;
32 |
--------------------------------------------------------------------------------
/Example/screens/TestDeeplinkingScreen2.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {StyleSheet, Text, View} from 'react-native';
3 | import Colors from "../constants/Colors.ts";
4 |
5 | const TestDeeplinkingScreen2: React.FC = () => {
6 | return (
7 |
8 |
9 | This screen was opened by the second deeplink
10 |
11 |
12 | );
13 | };
14 |
15 | const styles = StyleSheet.create({
16 | infoText: {
17 | margin: 5,
18 | fontSize: 20,
19 | fontWeight: 'bold',
20 | textAlign: 'center',
21 | lineHeight: 40,
22 | color: Colors.primaryGray,
23 | },
24 | infoView: {
25 | flex: 1,
26 | alignItems: 'center',
27 | justifyContent: 'center',
28 | },
29 | });
30 |
31 | export default TestDeeplinkingScreen2;
32 |
--------------------------------------------------------------------------------
/Example/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@react-native/typescript-config/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
3 | ruby '>= 2.6.10'
4 | gem 'cocoapods', '~> 1.11', '>= 1.11.3'
5 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.6)
5 | rexml
6 | activesupport (7.0.4.3)
7 | concurrent-ruby (~> 1.0, >= 1.0.2)
8 | i18n (>= 1.6, < 2)
9 | minitest (>= 5.1)
10 | tzinfo (~> 2.0)
11 | addressable (2.8.3)
12 | public_suffix (>= 2.0.2, < 6.0)
13 | algoliasearch (1.27.5)
14 | httpclient (~> 2.8, >= 2.8.3)
15 | json (>= 1.5.1)
16 | atomos (0.1.3)
17 | claide (1.1.0)
18 | cocoapods (1.12.0)
19 | addressable (~> 2.8)
20 | claide (>= 1.0.2, < 2.0)
21 | cocoapods-core (= 1.12.0)
22 | cocoapods-deintegrate (>= 1.0.3, < 2.0)
23 | cocoapods-downloader (>= 1.6.0, < 2.0)
24 | cocoapods-plugins (>= 1.0.0, < 2.0)
25 | cocoapods-search (>= 1.0.0, < 2.0)
26 | cocoapods-trunk (>= 1.6.0, < 2.0)
27 | cocoapods-try (>= 1.1.0, < 2.0)
28 | colored2 (~> 3.1)
29 | escape (~> 0.0.4)
30 | fourflusher (>= 2.3.0, < 3.0)
31 | gh_inspector (~> 1.0)
32 | molinillo (~> 0.8.0)
33 | nap (~> 1.0)
34 | ruby-macho (>= 2.3.0, < 3.0)
35 | xcodeproj (>= 1.21.0, < 2.0)
36 | cocoapods-core (1.12.0)
37 | activesupport (>= 5.0, < 8)
38 | addressable (~> 2.8)
39 | algoliasearch (~> 1.0)
40 | concurrent-ruby (~> 1.1)
41 | fuzzy_match (~> 2.0.4)
42 | nap (~> 1.0)
43 | netrc (~> 0.11)
44 | public_suffix (~> 4.0)
45 | typhoeus (~> 1.0)
46 | cocoapods-deintegrate (1.0.5)
47 | cocoapods-downloader (1.6.3)
48 | cocoapods-plugins (1.0.0)
49 | nap
50 | cocoapods-search (1.0.1)
51 | cocoapods-trunk (1.6.0)
52 | nap (>= 0.8, < 2.0)
53 | netrc (~> 0.11)
54 | cocoapods-try (1.2.0)
55 | colored2 (3.1.2)
56 | concurrent-ruby (1.2.2)
57 | escape (0.0.4)
58 | ethon (0.16.0)
59 | ffi (>= 1.15.0)
60 | ffi (1.15.5)
61 | fourflusher (2.3.1)
62 | fuzzy_match (2.0.4)
63 | gh_inspector (1.1.3)
64 | httpclient (2.8.3)
65 | i18n (1.12.0)
66 | concurrent-ruby (~> 1.0)
67 | json (2.6.3)
68 | minitest (5.18.0)
69 | molinillo (0.8.0)
70 | nanaimo (0.3.0)
71 | nap (1.1.0)
72 | netrc (0.11.0)
73 | public_suffix (4.0.7)
74 | rexml (3.2.5)
75 | ruby-macho (2.5.1)
76 | typhoeus (1.4.0)
77 | ethon (>= 0.9.0)
78 | tzinfo (2.0.6)
79 | concurrent-ruby (~> 1.0)
80 | xcodeproj (1.22.0)
81 | CFPropertyList (>= 2.3.3, < 4.0)
82 | atomos (~> 0.1.3)
83 | claide (>= 1.0.2, < 2.0)
84 | colored2 (~> 3.1)
85 | nanaimo (~> 0.3.0)
86 | rexml (~> 3.2.4)
87 |
88 | PLATFORMS
89 | ruby
90 |
91 | DEPENDENCIES
92 | cocoapods (~> 1.11, >= 1.11.3)
93 |
94 | RUBY VERSION
95 | ruby 2.7.5p203
96 |
97 | BUNDLED WITH
98 | 2.2.27
99 |
--------------------------------------------------------------------------------
/android/README.md:
--------------------------------------------------------------------------------
1 | README
2 | ======
3 |
4 | If you want to publish the lib as a maven dependency, follow these steps before publishing a new version to npm:
5 |
6 | 1. Be sure to have the Android [SDK](https://developer.android.com/studio/index.html) and [NDK](https://developer.android.com/ndk/guides/index.html) installed
7 | 2. Be sure to have a `local.properties` file in this folder that points to the Android SDK and NDK
8 | ```
9 | ndk.dir=/Users/{username}/Library/Android/sdk/ndk-bundle
10 | sdk.dir=/Users/{username}/Library/Android/sdk
11 | ```
12 | 3. Delete the `maven` folder
13 | 4. Run `./gradlew installArchives`
14 | 5. Verify that latest set of generated files is in the maven folder with the correct version number
15 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | def defaultCompileSDKVersion = 35
2 | def defaultBuildToolsVersion = '35.0.0'
3 | def defaultMinSDKVersion = 21
4 | def defaultTargetSDKVersion = 35
5 |
6 | def getRootProjectProperty(property, fallback) {
7 | rootProject.ext.has(property) ? rootProject.ext.get(property) : fallback
8 | }
9 |
10 | def overrideGmsVersion = getRootProjectProperty('overrideGmsVersion', '')
11 | def overrideFirebaseVersion = getRootProjectProperty('overrideFirebaseVersion', '')
12 | def overrideKotlinVersion = getRootProjectProperty('overrideKotlinVersion', '')
13 | def withCryptorMigration = getRootProjectProperty('withCryptorMigration', false)
14 | def withWebRTCUI = getRootProjectProperty('withWebRTCUI', false)
15 |
16 | apply plugin: 'com.android.library'
17 | apply plugin: 'maven-publish'
18 |
19 | buildscript {
20 | // The Android Gradle plugin is only required when opening the android folder stand-alone.
21 | // This avoids unnecessary downloads and potential conflicts when the library is included as a
22 | // module dependency in an application project.
23 | // ref: https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#sec:build_script_external_dependencies
24 | if (project == rootProject) {
25 | repositories {
26 | google()
27 | mavenLocal()
28 | mavenCentral {
29 | // We don't want to fetch react-native from Maven Central as there are
30 | // older versions over there.
31 | content {
32 | excludeGroup "com.facebook.react"
33 | }
34 | }
35 | }
36 | dependencies {
37 | classpath 'com.android.tools.build:gradle:8.5.2'
38 | }
39 | }
40 | }
41 |
42 | apply plugin: 'com.android.library'
43 | apply plugin: 'maven-publish'
44 |
45 | android {
46 | namespace "org.infobip.reactlibrary.mobilemessaging"
47 | compileSdkVersion getRootProjectProperty('compileSdkVersion', defaultCompileSDKVersion)
48 | buildToolsVersion getRootProjectProperty('buildToolsVersion', defaultBuildToolsVersion)
49 | defaultConfig {
50 | minSdkVersion getRootProjectProperty('minSdkVersion', defaultMinSDKVersion)
51 | targetSdkVersion getRootProjectProperty('targetSdkVersion', defaultTargetSDKVersion)
52 | versionCode 1
53 | versionName "1.0"
54 | }
55 |
56 | buildTypes {
57 | release {
58 | // Applying ProGuard rules for application classes that will be serialized/deserialized over Gson
59 | consumerProguardFiles 'infobip-mm-proguard-rules.pro'
60 | }
61 | }
62 |
63 | lintOptions {
64 | abortOnError false
65 | }
66 | }
67 |
68 | repositories {
69 | // ref: https://www.baeldung.com/maven-local-repository
70 | maven {
71 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
72 | url "$rootDir/../node_modules/react-native/android"
73 | }
74 | maven {
75 | // Android JSC is installed from npm
76 | url "$rootDir/../node_modules/jsc-android/dist"
77 | }
78 | mavenCentral {
79 | // We don't want to fetch react-native from Maven Central as there are
80 | // older versions over there.
81 | content {
82 | excludeGroup "com.facebook.react"
83 | }
84 | }
85 | google()
86 | mavenLocal()
87 | }
88 |
89 | dependencies {
90 | def mmVersion = '13.18.0'
91 | //react and mm dependencies clash
92 | if (!overrideKotlinVersion.empty) {
93 | constraints {
94 | implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$overrideKotlinVersion")
95 | }
96 | }
97 | implementation 'com.facebook.react:react-native:+'
98 | implementation "androidx.annotation:annotation:1.1.0"
99 |
100 | implementation 'com.google.android.material:material:1.8.0'
101 | implementation 'androidx.exifinterface:exifinterface:1.3.6'
102 | implementation 'androidx.databinding:viewbinding:8.0.2'
103 | implementation 'com.google.android.gms:play-services-base:18.2.0'
104 |
105 | implementation "com.infobip:infobip-mobile-messaging-android-resources:$mmVersion@aar"
106 | implementation "com.infobip:infobip-mobile-messaging-android-chat-sdk:$mmVersion@aar"
107 | implementation "com.infobip:infobip-mobile-messaging-android-inbox-sdk:$mmVersion@aar"
108 | implementation ("com.infobip:infobip-mobile-messaging-android-sdk:$mmVersion@aar") {
109 | transitive = true;
110 |
111 | if (!overrideGmsVersion.empty) {
112 | exclude group: 'com.google.android.gms', module: 'play-services-location'
113 | }
114 | if (!overrideFirebaseVersion.empty) {
115 | exclude group: 'com.google.firebase', module: 'firebase-messaging'
116 | }
117 | }
118 | if (withWebRTCUI.toBoolean()) {
119 | implementation implementation("com.infobip:infobip-rtc-ui:$mmVersion") {
120 | transitive = true
121 | }
122 | }
123 | if (!overrideGmsVersion.empty) {
124 | implementation "com.google.android.gms:play-services-location:$overrideGmsVersion"
125 | }
126 | if (!overrideFirebaseVersion.empty) {
127 | implementation "com.google.firebase:firebase-messaging:$overrideFirebaseVersion"
128 | }
129 |
130 | if (withCryptorMigration.toBoolean()) {
131 | implementation "com.infobip:infobip-mobile-messaging-android-cryptor-migration:$mmVersion@aar"
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | android.useAndroidX=true
2 | android.enableJetifier=true
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infobip/mobile-messaging-react-native-plugin/8f06811bcccf07b2ee8640e81cb4e1e8a600ba8b/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Jun 02 12:54:06 MSK 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
7 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/android/infobip-mm-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 |
12 | # Application classes that will be serialized/deserialized over Gson
13 | -keep class org.infobip.reactlibrary.mobilemessaging.Configuration* { *; }
14 | -keep class org.infobip.reactlibrary.mobilemessaging.Configuration$* { *; }
15 | -keep class org.infobip.reactlibrary.mobilemessaging.CacheManager* { *; }
16 | -keep class org.infobip.reactlibrary.mobilemessaging.ChatCustomization* { *; }
17 | -keep class org.infobip.reactlibrary.mobilemessaging.ChatCustomization$* { *; }
18 |
19 | # InfobipRtcUi classes that are accessed via reflection
20 | -keep class com.infobip.webrtc.ui.InfobipRtcUi$Builder { *; }
21 | -keep class com.infobip.webrtc.ui.SuccessListener { *; }
22 | -keep class com.infobip.webrtc.ui.ErrorListener { *; }
23 | -keep class com.infobip.webrtc.ui.InfobipRtcUi { *; }
24 |
25 |
26 | # Application classes that are used by native MM SDK
27 |
28 | # Preserve all annotations.
29 | -keepattributes *Annotation*
30 |
31 | # Preserve all .class method names.
32 | -keepclassmembernames class org.infobip.reactlibrary.mobilemessaging.** {
33 | java.lang.Class class$(java.lang.String);
34 | java.lang.Class class$(java.lang.String, boolean);
35 | }
36 |
37 | # Preserve all native method names and the names of their classes.
38 | -keepclasseswithmembernames class org.infobip.reactlibrary.mobilemessaging.** {
39 | native ;
40 | }
41 |
42 | # Preserve the special static methods that are required in all enumeration
43 | # classes.
44 | -keepclassmembers class org.infobip.reactlibrary.mobilemessaging.** extends java.lang.Enum {
45 | ;
46 | public static **[] values();
47 | public static ** valueOf(java.lang.String);
48 | }
49 |
50 | # Explicitly preserve all serialization members. The Serializable interface
51 | # is only a marker interface, so it wouldn't save them.
52 | # You can comment this out if your library doesn't use serialization.
53 | # If your code contains serializable classes that have to be backward
54 | # compatible, please refer to the manual.
55 | -keepclassmembers class org.infobip.reactlibrary.mobilemessaging.** implements java.io.Serializable {
56 | static final long serialVersionUID;
57 | static final java.io.ObjectStreamField[] serialPersistentFields;
58 | private void writeObject(java.io.ObjectOutputStream);
59 | private void readObject(java.io.ObjectInputStream);
60 | java.lang.Object writeReplace();
61 | java.lang.Object readResolve();
62 | }
63 |
64 | # Preserve methonds used by Java reflection
65 | -keepclassmembers class org.infobip.reactlibrary.mobilemessaging.ReactNativeMobileMessagingModule$* {
66 | public (...);
67 | }
68 |
69 | # Preserve all ReactNativeMobileMessagingModule inner classes used by Android MM SDK
70 | -keep class org.infobip.reactlibrary.mobilemessaging.ReactNativeMobileMessagingModule* { *; }
71 | -keep class org.infobip.reactlibrary.mobilemessaging.ReactNativeMobileMessagingModule$* { *; }
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
33 |
34 |
38 |
39 |
44 |
45 |
49 |
50 |
51 |
52 |
53 |
54 |
56 |
57 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/android/src/main/java/org/infobip/reactlibrary/mobilemessaging/CacheManager.java:
--------------------------------------------------------------------------------
1 | package org.infobip.reactlibrary.mobilemessaging;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.preference.PreferenceManager;
6 |
7 | import org.infobip.mobile.messaging.api.support.http.serialization.JsonSerializer;
8 | import org.infobip.mobile.messaging.dal.json.JSONArrayAdapter;
9 | import org.infobip.mobile.messaging.dal.json.JSONObjectAdapter;
10 | import org.json.JSONObject;
11 |
12 | import java.util.ArrayList;
13 | import java.util.Arrays;
14 | import java.util.HashSet;
15 | import java.util.List;
16 | import java.util.Set;
17 |
18 | class CacheManager {
19 | private static final String EVENTS_KEY = Utils.TAG + ".cache.events";
20 | private static final Object cacheLock = new Object();
21 | private static final JsonSerializer serializer = new JsonSerializer(false, new JSONObjectAdapter(), new JSONArrayAdapter());
22 |
23 | static class Event {
24 | String type;
25 | JSONObject jsonObject;
26 | Object[] objects = null;
27 |
28 | Event(String type, JSONObject object, Object... objects) {
29 | this.type = type;
30 | this.jsonObject = object;
31 | this.objects = objects;
32 | }
33 |
34 | @Override
35 | public String toString() {
36 | return type;
37 | }
38 |
39 | }
40 |
41 | static void saveEvent(Context context, String event, JSONObject object, String actionId, String actionInputText) {
42 | String serialized = serializer.serialize(new Event(event, object, actionId, actionInputText));
43 | saveStringsToSet(context, EVENTS_KEY, serialized);
44 | }
45 |
46 | static void saveEvent(Context context, String event, int unreadMessagesCounter) {
47 | //int `unreadMessagesCounter` isn't a JSONObject, so it'll go as a second argument
48 | String serialized = serializer.serialize(new Event(event, null, unreadMessagesCounter));
49 | saveStringsToSet(context, EVENTS_KEY, serialized);
50 | }
51 |
52 | static Event[] loadEvents(Context context) {
53 | Set serialized = getAndRemoveStringSet(context, EVENTS_KEY);
54 | List events = new ArrayList(serialized.size());
55 | for (String s : serialized) {
56 | events.add(serializer.deserialize(s, Event.class));
57 | }
58 | return events.toArray(new Event[events.size()]);
59 | }
60 |
61 | private static Set getAndRemoveStringSet(Context context, String key) {
62 | SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
63 | Set set;
64 | synchronized (cacheLock) {
65 | set = sharedPreferences.getStringSet(key, new HashSet());
66 | if (set.isEmpty()) {
67 | return new HashSet();
68 | }
69 | sharedPreferences
70 | .edit()
71 | .remove(key)
72 | .apply();
73 | }
74 | return set;
75 | }
76 |
77 | @SuppressWarnings("UnusedReturnValue")
78 | private static Set saveStringsToSet(Context context, String key, String... strings) {
79 | return saveStringSet(context, key, new HashSet(Arrays.asList(strings)));
80 | }
81 |
82 | private static Set saveStringSet(Context context, String key, Set newSet) {
83 | SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
84 | synchronized (cacheLock) {
85 | Set set = sharedPreferences.getStringSet(key, new HashSet());
86 | newSet.addAll(set);
87 | sharedPreferences
88 | .edit()
89 | .putStringSet(key, newSet)
90 | .apply();
91 | return set;
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/android/src/main/java/org/infobip/reactlibrary/mobilemessaging/ConfigCache.java:
--------------------------------------------------------------------------------
1 | package org.infobip.reactlibrary.mobilemessaging;
2 |
3 | public class ConfigCache {
4 | private static final ConfigCache INSTANCE = new ConfigCache();
5 |
6 | private Configuration configuration = null;
7 |
8 | private ConfigCache() {
9 | }
10 |
11 | public static ConfigCache getInstance() {
12 | return INSTANCE;
13 | }
14 |
15 | public Configuration getConfiguration() {
16 | return configuration;
17 | }
18 |
19 | public void setConfiguration(Configuration configuration) {
20 | this.configuration = configuration;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/android/src/main/java/org/infobip/reactlibrary/mobilemessaging/Configuration.java:
--------------------------------------------------------------------------------
1 | package org.infobip.reactlibrary.mobilemessaging;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import com.google.firebase.FirebaseOptions;
6 |
7 | import org.infobip.mobile.messaging.api.support.http.serialization.JsonSerializer;
8 | import org.json.JSONException;
9 | import org.json.JSONObject;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | class Configuration {
16 |
17 | class AndroidConfiguration {
18 | String notificationIcon;
19 | String notificationChannelId;
20 | String notificationChannelName;
21 | String notificationSound;
22 | boolean multipleNotifications;
23 | String notificationAccentColor;
24 | FirebaseOptions firebaseOptions;
25 | }
26 |
27 | class PrivacySettings {
28 | boolean userDataPersistingDisabled;
29 | boolean carrierInfoSendingDisabled;
30 | boolean systemInfoSendingDisabled;
31 | }
32 |
33 | class Action {
34 | String identifier;
35 | String title;
36 | boolean foreground;
37 | boolean moRequired;
38 | String icon;
39 | String textInputPlaceholder;
40 | }
41 |
42 | class Category {
43 | String identifier;
44 | List actions;
45 | }
46 |
47 | class InAppChatCustomization {
48 | //common
49 | String widgetTheme;
50 | String toolbarTitle;
51 | String toolbarTitleColor;
52 | String toolbarBackgroundColor;
53 | String chatBackgroundColor;
54 | String noConnectionAlertTextColor;
55 | String noConnectionAlertBackgroundColor;
56 | String chatInputPlaceholderTextColor;
57 | String chatInputCursorColor;
58 | String chatInputBackgroundColor;
59 | String sendButtonIconUri;
60 | String attachmentButtonIconUri;
61 | boolean chatInputSeparatorVisible;
62 | //android only
63 | //status bar properties
64 | boolean statusBarColorLight;
65 | String statusBarBackgroundColor;
66 | //toolbar properties
67 | String navigationIconUri;
68 | String navigationIconTint;
69 | String subtitleText;
70 | String subtitleTextColor;
71 | String subtitleTextAppearanceRes;
72 | boolean subtitleCentered;
73 | String titleTextAppearanceRes;
74 | boolean titleCentered;
75 | String menuItemsIconTint;
76 | String menuItemSaveAttachmentIcon;
77 | //chat properties
78 | String progressBarColor;
79 | String networkConnectionErrorTextAppearanceRes;
80 | String networkConnectionErrorText;
81 | //chat input properties
82 | String inputTextColor;
83 | String inputAttachmentIconTint;
84 | String inputAttachmentBackgroundColor;
85 | String inputAttachmentBackgroundDrawable;
86 | String inputSendIconTint;
87 | String inputSendBackgroundColor;
88 | String inputSendBackgroundDrawable;
89 | String inputSeparatorLineColor;
90 | String inputHintText;
91 | String inputTextAppearance;
92 | }
93 |
94 | class WebRTCUI {
95 | String configurationId;
96 | }
97 |
98 | AndroidConfiguration android;
99 | String applicationCode;
100 | boolean inAppChatEnabled;
101 | boolean fullFeaturedInAppsEnabled;
102 | Map messageStorage;
103 | boolean defaultMessageStorage;
104 | boolean loggingEnabled;
105 | String reactNativePluginVersion = "unknown";
106 | PrivacySettings privacySettings = new PrivacySettings();
107 | List notificationCategories = new ArrayList();
108 | WebRTCUI webRTCUI;
109 | InAppChatCustomization inAppChatCustomization;
110 |
111 | @NonNull
112 | static Configuration resolveConfiguration(JSONObject args) throws JSONException {
113 | if (args == null) {
114 | throw new IllegalArgumentException("Cannot resolve configuration from arguments");
115 | }
116 |
117 | Configuration config = new JsonSerializer().deserialize(args.toString(), Configuration.class);
118 | if (config == null || config.applicationCode == null) {
119 | throw new IllegalArgumentException("Configuration is invalid");
120 | }
121 |
122 | return config;
123 | }
124 |
125 | @NonNull
126 | static InAppChatCustomization resolveChatSettings(JSONObject args) throws JSONException {
127 | if (args == null) {
128 | throw new IllegalArgumentException("Cannot resolve configuration from arguments");
129 | }
130 |
131 | InAppChatCustomization config = new JsonSerializer().deserialize(args.toString(), InAppChatCustomization.class);
132 | if (config == null) {
133 | throw new IllegalArgumentException("Configuration is invalid");
134 | }
135 |
136 | return config;
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/android/src/main/java/org/infobip/reactlibrary/mobilemessaging/RNMMChatViewManager.java:
--------------------------------------------------------------------------------
1 | package org.infobip.reactlibrary.mobilemessaging;
2 |
3 | import android.util.Log;
4 | import android.widget.FrameLayout;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.annotation.Nullable;
8 |
9 | import com.facebook.react.bridge.ReactApplicationContext;
10 | import com.facebook.react.bridge.ReadableArray;
11 | import com.facebook.react.uimanager.ThemedReactContext;
12 | import com.facebook.react.uimanager.ViewGroupManager;
13 | import com.facebook.react.uimanager.annotations.ReactProp;
14 |
15 | class RNMMChatViewManager extends ViewGroupManager {
16 | public static final String COMMAND_ADD = "add";
17 | public static final String COMMAND_REMOVE = "remove";
18 |
19 | public static final String VIEW_GROUP_MANAGER_NAME = "RNMMChatView";
20 | private ReactApplicationContext context;
21 |
22 | @Nullable
23 | private ReactChatView chatView;
24 |
25 | @NonNull
26 | @Override
27 | public String getName() {
28 | return VIEW_GROUP_MANAGER_NAME;
29 | }
30 |
31 | public RNMMChatViewManager(ReactApplicationContext context) {
32 | this.context = context;
33 | }
34 |
35 | @NonNull
36 | @Override
37 | protected ReactChatView createViewInstance(@NonNull ThemedReactContext reactContext) {
38 | chatView = new ReactChatView(reactContext);
39 | return chatView;
40 | }
41 |
42 | @Override
43 | public void receiveCommand(@NonNull ReactChatView root, String commandId, @Nullable ReadableArray args) {
44 | super.receiveCommand(root, commandId, args);
45 |
46 | if (args == null) {
47 | Log.e(Utils.TAG, "RNMMChatViewManager received command without argumnents, Id: " + commandId);
48 | return;
49 | }
50 | int reactNativeViewId = args.getInt(0);
51 |
52 | switch (commandId) {
53 | case COMMAND_ADD:
54 | addChatFragment(root, reactNativeViewId);
55 | break;
56 | case COMMAND_REMOVE:
57 | removeChatFragment(root);
58 | break;
59 | default: {
60 | Log.w(Utils.TAG, "RNMMChatViewManager received unsupported command with Id: " + commandId);
61 | }
62 | }
63 | }
64 |
65 | @Override
66 | public boolean needsCustomLayoutForChildren() {
67 | return true;
68 | }
69 |
70 | @ReactProp(name = "sendButtonColor")
71 | public void setSendButtonColor(ReactChatView view, String hexSendButtonColor) {
72 | view.setSendButtonColor(hexSendButtonColor, Utils.getFragmentActivity(this.context));
73 | }
74 |
75 | private void addChatFragment(FrameLayout parentLayout, int reactNativeViewId) {
76 | if (chatView != null) {
77 | chatView.addChatFragment(parentLayout, reactNativeViewId, Utils.getFragmentActivity(this.context));
78 | }
79 | }
80 |
81 | private void removeChatFragment(FrameLayout parentLayout) {
82 | if (chatView != null) {
83 | chatView.removeChatFragment(parentLayout, Utils.getFragmentActivity(this.context));
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/android/src/main/java/org/infobip/reactlibrary/mobilemessaging/ReactChatView.java:
--------------------------------------------------------------------------------
1 | package org.infobip.reactlibrary.mobilemessaging;
2 |
3 | import android.content.Context;
4 | import android.os.Build;
5 | import android.util.AttributeSet;
6 | import android.util.Log;
7 | import android.view.ViewGroup;
8 | import android.widget.FrameLayout;
9 |
10 | import androidx.annotation.NonNull;
11 | import androidx.annotation.Nullable;
12 | import androidx.annotation.RequiresApi;
13 | import androidx.fragment.app.Fragment;
14 | import androidx.fragment.app.FragmentActivity;
15 | import androidx.fragment.app.FragmentManager;
16 | import androidx.fragment.app.FragmentTransaction;
17 |
18 | import org.infobip.mobile.messaging.chat.InAppChat;
19 | import org.infobip.mobile.messaging.chat.view.InAppChatFragment;
20 |
21 | class ReactChatView extends FrameLayout {
22 |
23 | public ReactChatView(@NonNull Context context) {
24 | super(context);
25 | }
26 |
27 | public ReactChatView(@NonNull Context context, @Nullable AttributeSet attrs) {
28 | super(context, attrs);
29 | }
30 |
31 | public ReactChatView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
32 | super(context, attrs, defStyleAttr);
33 | }
34 |
35 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
36 | public ReactChatView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
37 | super(context, attrs, defStyleAttr, defStyleRes);
38 | }
39 |
40 | @Override
41 | public void requestLayout() {
42 | super.requestLayout();
43 |
44 | //RN issue https://github.com/facebook/react-native/issues/17968
45 | //Without this layout will not be called and view will not be displayed, because RN doesn't dispatches events to android views properly
46 | post(measureAndLayout);
47 | }
48 |
49 | public void setSendButtonColor(String hexColorString, @Nullable FragmentActivity fragmentActivity) {
50 | Log.d(Utils.TAG, "Not implemented for Android, use IB_AppTheme.Chat theme instead");
51 | }
52 |
53 | public void addChatFragment(FrameLayout parentLayout, int reactNativeViewId, @Nullable FragmentActivity fragmentActivity) {
54 | if (fragmentActivity == null) {
55 | return;
56 | }
57 |
58 | //RN issue https://github.com/facebook/react-native/issues/17968
59 | //Without this layout will not be called and view will not be displayed, because RN doesn't dispatches events to android views properly
60 | ViewGroup parentView = (ViewGroup) parentLayout.findViewById(reactNativeViewId).getParent();
61 | setupLayoutHack(parentView);
62 |
63 | FragmentManager fragmentManager = fragmentActivity.getSupportFragmentManager();
64 | InAppChat.getInstance(fragmentActivity.getApplicationContext()).showInAppChatFragment(fragmentManager, reactNativeViewId);
65 | fragmentManager.executePendingTransactions();
66 | Fragment inAppChatFragment = fragmentManager.findFragmentByTag(Utils.RN_IN_APP_CHAT_FRAGMENT_TAG);
67 | Log.e(Utils.TAG, "InAppChatFragment found " + (inAppChatFragment != null));
68 | if (inAppChatFragment instanceof InAppChatFragment) {
69 | ((InAppChatFragment) inAppChatFragment).setWithToolbar(false);
70 | }
71 | }
72 |
73 | public void removeChatFragment(FrameLayout parentLayout, @Nullable FragmentActivity fragmentActivity) {
74 | if (fragmentActivity == null) {
75 | return;
76 | }
77 | FragmentManager fragmentManager = fragmentActivity.getSupportFragmentManager();
78 | FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
79 | Fragment fragment = fragmentManager.findFragmentByTag(Utils.RN_IN_APP_CHAT_FRAGMENT_TAG);
80 | if (fragment != null) {
81 | fragmentTransaction.remove(fragment);
82 | }
83 | fragmentTransaction.commit();
84 | }
85 |
86 | private void setupLayoutHack(final ViewGroup view) {
87 | view.getViewTreeObserver().addOnGlobalLayoutListener(view::requestLayout);
88 | }
89 |
90 | private final Runnable measureAndLayout = () -> {
91 | measure(
92 | MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY),
93 | MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY));
94 | layout(getLeft(), getTop(), getRight(), getBottom());
95 | };
96 | }
97 |
--------------------------------------------------------------------------------
/android/src/main/java/org/infobip/reactlibrary/mobilemessaging/ReactNativeEvent.java:
--------------------------------------------------------------------------------
1 | package org.infobip.reactlibrary.mobilemessaging;
2 |
3 | import android.util.Log;
4 |
5 | import com.facebook.react.bridge.ReactContext;
6 | import com.facebook.react.bridge.ReadableArray;
7 | import com.facebook.react.bridge.ReadableMap;
8 | import com.facebook.react.bridge.WritableArray;
9 | import com.facebook.react.bridge.WritableNativeArray;
10 | import com.facebook.react.modules.core.DeviceEventManagerModule;
11 |
12 | import org.infobip.reactlibrary.mobilemessaging.datamappers.ReactNativeJson;
13 | import org.json.JSONArray;
14 | import org.json.JSONException;
15 | import org.json.JSONObject;
16 |
17 |
18 | class ReactNativeEvent {
19 |
20 | static void send(String eventName, ReactContext reactContext, Object... objects) {
21 | send(eventName, reactContext, null, objects);
22 | }
23 |
24 | static void send(String eventName, ReactContext reactContext, JSONObject jsonObject, Object... objects) {
25 | if (jsonObject == null && objects == null) {
26 | Log.d(Utils.TAG, "objects are null, so another method should be used");
27 | send(eventName, reactContext);
28 | return;
29 | }
30 |
31 | WritableArray array = new WritableNativeArray();
32 |
33 | try {
34 |
35 | if (jsonObject != null) {
36 | array.pushMap(ReactNativeJson.convertJsonToMap(jsonObject));
37 | }
38 |
39 | for (Object value : objects) {
40 | if (value == null) {
41 | continue;
42 | }
43 | if (value instanceof JSONObject) {
44 | array.pushMap(ReactNativeJson.convertJsonToMap((JSONObject) value));
45 | } else if (value instanceof JSONArray) {
46 | array.pushArray(ReactNativeJson.convertJsonToArray((JSONArray) value));
47 | } else if (value instanceof Boolean) {
48 | array.pushBoolean((Boolean) value);
49 | } else if (value instanceof Integer) {
50 | array.pushInt((Integer) value);
51 | } else if (value instanceof Double) {
52 | array.pushDouble((Double) value);
53 | } else if (value instanceof String) {
54 | array.pushString((String) value);
55 | } else {
56 | array.pushString(value.toString());
57 | }
58 | }
59 | } catch (JSONException e) {
60 | Log.e(Utils.TAG, "Arguments can't be converted to JS types");
61 | }
62 | send(eventName, reactContext, array);
63 | }
64 |
65 | static void send(String eventName, ReactContext reactContext, ReadableMap map) {
66 | if (eventName == null || map == null) {
67 | return;
68 | }
69 |
70 | reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, map);
71 | }
72 |
73 | static void send(String eventName, ReactContext reactContext, ReadableArray array) {
74 | if (eventName == null || array == null) {
75 | return;
76 | }
77 |
78 | reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, array);
79 | }
80 |
81 | static void send(String eventName, ReactContext reactContext) {
82 | if (eventName == null) {
83 | return;
84 | }
85 | reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, null);
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/android/src/main/java/org/infobip/reactlibrary/mobilemessaging/ReactNativeMobileMessagingPackage.java:
--------------------------------------------------------------------------------
1 | package org.infobip.reactlibrary.mobilemessaging;
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.Arrays;
12 | import java.util.List;
13 |
14 | public class ReactNativeMobileMessagingPackage implements ReactPackage {
15 |
16 | @NonNull
17 | @Override
18 | public List createNativeModules(@NonNull ReactApplicationContext reactContext) {
19 | List modules = new ArrayList<>();
20 | modules.add(new ReactNativeMobileMessagingModule(reactContext));
21 | modules.add(new RNMMChatModule(reactContext));
22 | modules.add(new RNMMWebRTCUI(reactContext));
23 | return modules;
24 | }
25 |
26 | @NonNull
27 | @Override
28 | public List createViewManagers(@NonNull ReactApplicationContext reactContext) {
29 | return Arrays.asList(new RNMMChatViewManager(reactContext));
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/android/src/main/java/org/infobip/reactlibrary/mobilemessaging/Utils.java:
--------------------------------------------------------------------------------
1 | package org.infobip.reactlibrary.mobilemessaging;
2 |
3 | import android.content.res.Resources;
4 | import android.util.Log;
5 |
6 | import androidx.annotation.Nullable;
7 | import androidx.fragment.app.FragmentActivity;
8 |
9 | import com.facebook.react.bridge.Callback;
10 | import com.facebook.react.bridge.ReactApplicationContext;
11 | import com.facebook.react.bridge.ReadableArray;
12 | import com.facebook.react.bridge.WritableMap;
13 | import com.facebook.react.bridge.WritableNativeMap;
14 |
15 | import org.infobip.mobile.messaging.chat.view.InAppChatFragment;
16 |
17 | public class Utils {
18 | public static final String TAG = "RNMobileMessaging";
19 | public static final String RN_IN_APP_CHAT_FRAGMENT_TAG = InAppChatFragment.class.getName();
20 | public static final int REQ_CODE_RESOLVE_GOOGLE_ERROR = 2;
21 |
22 | /**
23 | * Gets resource ID
24 | *
25 | * @param res the resources where to look for
26 | * @param resPath the name of the resource
27 | * @param packageName name of the package where the resource should be searched for
28 | * @return resource identifier or 0 if not found
29 | */
30 | static int getResId(Resources res, String resPath, String packageName) {
31 | int resId = res.getIdentifier(resPath, "mipmap", packageName);
32 | if (resId == 0) {
33 | resId = res.getIdentifier(resPath, "drawable", packageName);
34 | }
35 | if (resId == 0) {
36 | resId = res.getIdentifier(resPath, "raw", packageName);
37 | }
38 | if (resId == 0) {
39 | resId = res.getIdentifier(resPath, "style", packageName);
40 | }
41 |
42 | return resId;
43 | }
44 |
45 | static String[] resolveStringArray(ReadableArray args) {
46 | if (args.size() < 1 || args.getString(0) == null) {
47 | throw new IllegalArgumentException("Cannot resolve string parameters from arguments");
48 | }
49 |
50 | String[] array = new String[args.size()];
51 | for (int i = 0; i < args.size(); i++) {
52 | array[i] = args.getString(i);
53 | }
54 |
55 | return array;
56 | }
57 |
58 | public static class ReactNativeCallContext {
59 | Callback onSuccess;
60 | Callback onError;
61 |
62 | void reset() {
63 | onSuccess = null;
64 | onError = null;
65 | }
66 |
67 | boolean isValid() {
68 | return onSuccess != null && onError != null;
69 | }
70 | }
71 |
72 | public static WritableMap callbackError(String description, @Nullable Integer errorCode) {
73 | WritableMap errorMap = new WritableNativeMap();
74 | if (description != null && !description.isEmpty()) {
75 | errorMap.putString("description", description);
76 | }
77 | if (errorCode != null) {
78 | errorMap.putInt("code", errorCode);
79 | }
80 | return errorMap;
81 | }
82 |
83 | @Nullable
84 | public static FragmentActivity getFragmentActivity(ReactApplicationContext context) {
85 | FragmentActivity fragmentActivity = (FragmentActivity) context.getCurrentActivity();
86 | if (fragmentActivity == null) {
87 | Log.e(Utils.TAG, "RNMMChatViewManager can't get fragmentActivity");
88 | return null;
89 | }
90 | return fragmentActivity;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:metro-react-native-babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/infobip-mobile-messaging-react-native-plugin.podspec:
--------------------------------------------------------------------------------
1 | require "json"
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4 | mmVersion = "13.5.0"
5 |
6 | Pod::Spec.new do |s|
7 | s.name = "infobip-mobile-messaging-react-native-plugin"
8 | s.version = package["version"]
9 | s.summary = package["description"]
10 | s.description = <<-DESC
11 | infobip-mobile-messaging-react-native-plugin
12 | DESC
13 | s.homepage = "https://github.com/infobip/mobile-messaging-react-native-plugin"
14 | s.license = "MIT"
15 | s.authors = { "Infobip" => "Push.Support@infobip.com" }
16 | s.platforms = { :ios => "13.0" }
17 | s.source = { :git => 'https://github.com/infobip/mobile-messaging-react-native-plugin.git', :tag => s.version}
18 | s.swift_version = '5'
19 | s.source_files = "ios/**/*.{h,m,swift}"
20 | s.requires_arc = true
21 |
22 | s.dependency "React-Core"
23 |
24 | s.dependency "MobileMessaging/Core", mmVersion
25 | s.dependency "MobileMessaging/InAppChat", mmVersion
26 | s.dependency "MobileMessaging/Inbox", mmVersion
27 | if defined?($WebRTCUIEnabled)
28 | s.dependency "MobileMessaging/WebRTCUI", mmVersion
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/ios/MobileMessagingPlugin/RNMMChatBridge.m:
--------------------------------------------------------------------------------
1 | //
2 | // RNMMChatBridge.m
3 | // infobip-mobile-messaging-react-native-plugin
4 | //
5 | // Created by Olga Koroleva on 26.05.2020.
6 | //
7 |
8 | #import
9 | #import
10 |
11 | @interface RNMMChat : NSObject
12 | @end
13 |
14 | @interface RNMMChat (RCTExternModule)
15 | @end
16 |
17 | @implementation RNMMChat (RCTExternModule)
18 | RCT_EXPORT_MODULE_NO_LOAD(RNMMChat, RNMMChat)
19 | RCT_EXTERN_METHOD(showChat:)
20 | RCT_EXTERN_METHOD(getMessageCounter:(RCTResponseSenderBlock)resultCallback)
21 | RCT_EXTERN_METHOD(setWidgetTheme:)
22 | RCT_EXTERN_METHOD(setChatCustomization:)
23 | RCT_EXTERN_METHOD(setupChatSettings:)
24 | RCT_EXTERN_METHOD(setLanguage:(NSString *)data onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
25 | RCT_EXTERN_METHOD(setJwt:)
26 | RCT_EXTERN_METHOD(sendContextualData:(NSString *)data chatMultiThreadStrategy:(NSString *)chatMultiThreadStrategy onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
27 | RCT_EXTERN_METHOD(showThreadsList)
28 | RCT_EXTERN_METHOD(restartConnection)
29 | RCT_EXTERN_METHOD(stopConnection)
30 |
31 | - (dispatch_queue_t)methodQueue {
32 | return dispatch_get_main_queue();
33 | }
34 |
35 | + (BOOL)requiresMainQueueSetup {
36 | return true;
37 | }
38 | @end
39 |
--------------------------------------------------------------------------------
/ios/MobileMessagingPlugin/RNMMChatViewManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RNMMChatViewManager.swift
3 | // infobip-mobile-messaging-react-native-plugin
4 | //
5 | // Created by Olga Koroleva on 28.05.2020.
6 | //
7 |
8 | import Foundation
9 | import MobileMessaging
10 |
11 | @objc(RNMMChatViewManager)
12 | class RNMMChatViewManager: RCTViewManager {
13 | override func view() -> UIView! {
14 | return RNMMChatView()
15 | }
16 | }
17 |
18 |
19 | @objc class RNMMChatView: UIView {
20 | override init(frame: CGRect) {
21 | super.init(frame: frame)
22 | }
23 | required init?(coder aDecoder: NSCoder) {
24 | fatalError("init(coder:) has not been implemented")
25 | }
26 |
27 | weak static var viewController: MMChatViewController?
28 |
29 | @objc func setSendButtonColor(_ colorString: NSString) {
30 | MMChatSettings.settings.configureWith(rawConfig: ["sendButtonColor": colorString])
31 | }
32 |
33 | override func layoutSubviews() {
34 | super.layoutSubviews()
35 | RNMMChatView.viewController?.view.frame = bounds
36 | }
37 |
38 | override func didMoveToWindow() {
39 | embedViewController()
40 | super.didMoveToWindow()
41 | }
42 |
43 | override func removeFromSuperview() {
44 | RNMMChatView.viewController?.removeFromParent()
45 | super.removeFromSuperview()
46 | }
47 |
48 | private func embedViewController() {
49 | guard let parentVC = parentViewController else {
50 | return
51 | }
52 | guard let existingChatVC = parentVC.children.filter({ $0 is MMChatViewController }).first as? MMChatViewController else {
53 | let newChatVC = MMChatViewController.makeModalViewController()
54 | parentVC.addChild(newChatVC)
55 | addSubview(newChatVC.view)
56 | newChatVC.didMove(toParent: parentVC)
57 | RNMMChatView.viewController = newChatVC
58 | return
59 | }
60 | /* existingChatVC is the case of didMoveToWindow being triggered from the presentation of other view (ie RTCImageView) */
61 | RNMMChatView.viewController = existingChatVC
62 | }
63 | }
64 |
65 | extension UIView {
66 | var parentViewController: UIViewController? {
67 | var parentResponder: UIResponder? = self
68 | while parentResponder != nil {
69 | parentResponder = parentResponder!.next
70 | if let viewController = parentResponder as? UIViewController {
71 | return viewController
72 | }
73 | }
74 | return nil
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/ios/MobileMessagingPlugin/RNMMChatViewManagerBridge.m:
--------------------------------------------------------------------------------
1 | //
2 | // RNMMChatViewManagerBridge.m
3 | // infobip-mobile-messaging-react-native-plugin
4 | //
5 | // Created by Olga Koroleva on 28.05.2020.
6 | //
7 |
8 | #import
9 | #import
10 |
11 | @interface RNMMChatViewManager: NSObject
12 | @end
13 |
14 | @interface RNMMChatViewManager (Module)
15 | @end
16 |
17 | @implementation RNMMChatViewManager (Module)
18 | RCT_EXPORT_MODULE_NO_LOAD(RNMMChatView, RNMMChatViewManager)
19 | RCT_EXPORT_VIEW_PROPERTY(sendButtonColor, NSString *)
20 |
21 | - (dispatch_queue_t)methodQueue {
22 | return dispatch_get_main_queue();
23 | }
24 |
25 | + (BOOL)requiresMainQueueSetup {
26 | return true;
27 | }
28 | @end
29 |
--------------------------------------------------------------------------------
/ios/MobileMessagingPlugin/RNMMWebRTCUI.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RNMMWebRTCUI.swift
3 | // infobip-mobile-messaging-react-native-plugin
4 | //
5 | // Created by Francisco Fortes on 21.06.2022.
6 | //
7 |
8 | import Foundation
9 | import MobileMessaging
10 |
11 | @objc(RNMMWebRTCUI)
12 | class RNMMWebRTCUI: NSObject {
13 |
14 | #if WEBRTCUI_ENABLED
15 | private func handleCalls(
16 | _ identity: MMWebRTCIdentityMode,
17 | onSuccess: @escaping RCTResponseSenderBlock,
18 | onError: @escaping RCTResponseSenderBlock)
19 | {
20 | if let cachedConfigDict = RNMobileMessagingConfiguration.getRawConfigFromDefaults(),
21 | let configuration = RNMobileMessagingConfiguration(rawConfig: cachedConfigDict),
22 | let webRTCUI = configuration.webRTCUI,
23 | let webRTCId = webRTCUI[RNMobileMessagingConfiguration.Keys.configurationId] as? String {
24 | MobileMessaging.webRTCService?.configurationId = webRTCId
25 | MobileMessaging.webRTCService?.identityMode = identity
26 | MobileMessaging.webRTCService?.start({ result in
27 | switch result {
28 | case true:
29 | MMLogDebug("[WebRTCUI] Request for enabling calls ended with success")
30 | onSuccess(nil)
31 | case false:
32 | MMLogError("[WebRTCUI] Request for enabling calls ended with failure - See further logs.")
33 | onError(nil)
34 | }
35 | })
36 | } else {
37 | MMLogDebug("[WebRTCUI] WebRTC's configurationId not defined in the configuration, calls were not enabled.")
38 | onError([NSError(type: .InvalidArguments).reactNativeObject])
39 | }
40 | }
41 | #endif
42 |
43 | @objc(enableCalls:onSuccess:onError:)
44 | func enableCalls(
45 | identity: String,
46 | onSuccess: @escaping RCTResponseSenderBlock,
47 | onError: @escaping RCTResponseSenderBlock)
48 | {
49 | #if WEBRTCUI_ENABLED
50 | let identityMode: MMWebRTCIdentityMode = identity.isEmpty ? .default : .custom(identity)
51 | handleCalls(identityMode, onSuccess: onSuccess, onError: onError)
52 | #else
53 | MMLogDebug("[WebRTCUI] Not imported properly in podfile: library cannot be used.")
54 | onError([NSError(type: .NotSupported).reactNativeObject])
55 | #endif
56 | }
57 |
58 | @objc(enableChatCalls:onError:)
59 | func enableChatCalls(
60 | onSuccess: @escaping RCTResponseSenderBlock,
61 | onError: @escaping RCTResponseSenderBlock)
62 | {
63 | #if WEBRTCUI_ENABLED
64 | handleCalls(.inAppChat, onSuccess: onSuccess, onError: onError)
65 | #else
66 | MMLogDebug("[WebRTCUI] Not imported properly in podfile: library cannot be used.")
67 | onError([NSError(type: .NotSupported).reactNativeObject])
68 | #endif
69 | }
70 |
71 | @objc(disableCalls:onError:)
72 | func disableCalls(
73 | onSuccess: @escaping RCTResponseSenderBlock,
74 | onError: @escaping RCTResponseSenderBlock)
75 | {
76 | #if WEBRTCUI_ENABLED
77 | MobileMessaging.webRTCService?.stopService({ result in
78 | switch result {
79 | case true:
80 | MMLogDebug("[WebRTCUI] Request for disabling calls ended with success")
81 | onSuccess(nil)
82 | case false:
83 | MMLogError("[WebRTCUI] Request for disabling calls ended with failure - See further logs.")
84 | onError(nil)
85 | }
86 | })
87 | #else
88 | MMLogError("[WebRTCUI] Not imported properly in podfile: library cannot be used")
89 | onError([NSError(type: .NotSupported).reactNativeObject])
90 | #endif
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/ios/MobileMessagingPlugin/RNMMWebRTCUIBridge.m:
--------------------------------------------------------------------------------
1 | //
2 | // RNMMChatBridge.m
3 | // infobip-mobile-messaging-react-native-plugin
4 | //
5 | // Created by Olga Koroleva on 26.05.2020.
6 | //
7 |
8 | #import
9 | #import
10 |
11 | @interface RNMMWebRTCUI : NSObject
12 | @end
13 |
14 | @interface RNMMWebRTCUI (RCTExternModule)
15 | @end
16 |
17 | @implementation RNMMWebRTCUI (RCTExternModule)
18 | RCT_EXPORT_MODULE_NO_LOAD(RNMMWebRTCUI, RNMMWebRTCUI)
19 | RCT_EXTERN_METHOD(enableCalls:(NSString *)identity onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
20 | RCT_EXTERN_METHOD(enableChatCalls:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
21 | RCT_EXTERN_METHOD(disableCalls:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
22 |
23 |
24 | - (dispatch_queue_t)methodQueue {
25 | return dispatch_get_main_queue();
26 | }
27 |
28 | + (BOOL)requiresMainQueueSetup {
29 | return true;
30 | }
31 | @end
32 |
--------------------------------------------------------------------------------
/ios/MobileMessagingPlugin/RNMobileMessagingBridge.m:
--------------------------------------------------------------------------------
1 | //
2 | // MobileMessagingManagerSwiftBridge.m
3 | // ReactNativeMobileMessaging
4 | //
5 | // Created by Andrey Kadochnikov on 29.11.2019.
6 | //
7 |
8 | #import
9 | #import
10 | #import
11 |
12 | @interface ReactNativeMobileMessaging : RCTEventEmitter
13 | @end
14 |
15 | @interface ReactNativeMobileMessaging (RCTExternModule)
16 | @end
17 |
18 | @implementation ReactNativeMobileMessaging(RCTExternModule)
19 | RCT_EXPORT_MODULE_NO_LOAD(ReactNativeMobileMessaging, ReactNativeMobileMessaging)
20 |
21 | RCT_EXTERN_METHOD(init:(NSDictionary *)config onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
22 |
23 | /*User Profile Management*/
24 | RCT_EXTERN_METHOD(saveUser:(NSDictionary *)userData onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
25 | RCT_EXTERN_METHOD(fetchUser:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
26 | RCT_EXTERN_METHOD(getUser:(RCTResponseSenderBlock)successCallback)
27 | RCT_EXTERN_METHOD(saveInstallation:(NSDictionary *)installation onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
28 | RCT_EXTERN_METHOD(fetchInstallation:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
29 | RCT_EXTERN_METHOD(getInstallation:(RCTResponseSenderBlock)successCallback)
30 | RCT_EXTERN_METHOD(setInstallationAsPrimary:(NSString *)pushRegistrationId primary:(BOOL)primary onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
31 | RCT_EXTERN_METHOD(personalize:(NSDictionary *)context onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
32 | RCT_EXTERN_METHOD(depersonalize:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
33 | RCT_EXTERN_METHOD(depersonalizeInstallation:(NSString *)pushRegistrationId onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
34 |
35 | /*Messages and Notifications*/
36 | RCT_EXTERN_METHOD(markMessagesSeen:(NSArray *)messageIds onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
37 | RCT_EXTERN_METHOD(defaultMessageStorage_find:(NSString *)messageId onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
38 | RCT_EXTERN_METHOD(defaultMessageStorage_findAll:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
39 | RCT_EXTERN_METHOD(defaultMessageStorage_delete:(NSString *)messageId onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
40 | RCT_EXTERN_METHOD(defaultMessageStorage_deleteAll:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
41 | RCT_EXTERN_METHOD(messageStorage_provideFindResult:(NSDictionary *)message)
42 | RCT_EXTERN_METHOD(messageStorage_provideFindAllResult:(NSArray *)message)
43 | /*Events*/
44 | RCT_EXTERN_METHOD(submitEvent:(NSDictionary *)eventData onError:(RCTResponseSenderBlock)errorCallback)
45 | RCT_EXTERN_METHOD(submitEventImmediately:(NSDictionary *)eventData onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
46 | /*
47 | It's not supported for iOS, created for compatibility
48 | */
49 | RCT_EXTERN_METHOD(showDialogForError:(int)errorCode onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
50 |
51 | /*Inbox*/
52 | RCT_EXTERN_METHOD(fetchInboxMessages:(NSString *)token externalUserId:(NSString *)externalUserId inboxFilterOptions:(NSDictionary *)inboxFilterOptions onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
53 | RCT_EXTERN_METHOD(fetchInboxMessagesWithoutToken:(NSString *)externalUserId inboxFilterOptions:(NSDictionary *)inboxFilterOptions onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
54 | RCT_EXTERN_METHOD(setInboxMessagesSeen:(NSString *)externalUserId messages:(NSArray *)messages onSuccess:(RCTResponseSenderBlock)successCallback onError:(RCTResponseSenderBlock)errorCallback)
55 | @end
56 |
57 |
--------------------------------------------------------------------------------
/ios/MobileMessagingPlugin/RNMobileMessagingErrorExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RNMobileMessagingErrorExtension.swift
3 | // MobileMessaging
4 | //
5 | // Created by Olga Koroleva on 04.02.2020.
6 | //
7 |
8 | import Foundation
9 |
10 | public let RNMobileMessagingErrorDomain = "com.mobile-messaging-react-native-plugin"
11 |
12 | public enum RNMobileMessagingErrorType: Error {
13 | case InvalidArguments
14 | case InvalidUserIdentity
15 | case DefaultStorageNotInitialized
16 | case NotSupported
17 | case NoData
18 |
19 | fileprivate var errorCode: Int {
20 | switch self {
21 | case .InvalidArguments:
22 | return 0
23 | case .InvalidUserIdentity:
24 | return 1
25 | case .DefaultStorageNotInitialized:
26 | return 2
27 | case .NotSupported:
28 | return 3
29 | case .NoData:
30 | return 4
31 | }
32 |
33 | }
34 |
35 | fileprivate var errorDescription: String {
36 | var errorDescription: String = ""
37 |
38 | switch self {
39 | case .InvalidArguments:
40 | errorDescription = NSLocalizedString("Could not retrieve required arguments.", comment: "")
41 | case .InvalidUserIdentity:
42 | errorDescription = NSLocalizedString("userIdentity must have at least one non-nil property.", comment: "")
43 | case .DefaultStorageNotInitialized:
44 | errorDescription = NSLocalizedString("Default storage not initialized.", comment: "")
45 | case .NotSupported:
46 | errorDescription = NSLocalizedString("Functionality is not supported.", comment: "")
47 | case .NoData:
48 | errorDescription = NSLocalizedString("No data retrieved.", comment: "")
49 | }
50 | return errorDescription
51 | }
52 |
53 | var userInfo: [String: String] {
54 | return [NSLocalizedDescriptionKey: errorDescription]
55 | }
56 |
57 | }
58 |
59 | extension NSError {
60 | public convenience init(type: RNMobileMessagingErrorType) {
61 | self.init(domain: RNMobileMessagingErrorDomain, code: type.errorCode, userInfo: type.userInfo)
62 | }
63 |
64 | var reactNativeObject: [String: Any?] {
65 | return [
66 | "description": localizedDescription,
67 | "code": code,
68 | "domain": domain
69 | ]
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/ios/MobileMessagingPlugin/RNMobileMessagingStorageAdapter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RNMobileMessagingStorageAdapter.swift
3 | // infobip-mobile-messaging-react-native-plugin
4 | //
5 | // Created by Olga Koroleva on 12.02.2020.
6 | //
7 |
8 | import Foundation
9 | import MobileMessaging
10 |
11 | class MessageStorageAdapter: MMMessageStorage {
12 | let queue = DispatchQueue(label: "MessageStoreAdapterQueue")
13 | let findSemaphore = DispatchSemaphore(value: 0)
14 | var foundMessage:MMBaseMessage?
15 |
16 | private var eventEmitter: RCTEventEmitter!
17 |
18 | init(eventEmitter: RCTEventEmitter) {
19 | self.eventEmitter = eventEmitter
20 | }
21 |
22 | func start() {
23 | eventEmitter.sendEvent(withName: EventName.messageStorage_start, body: nil)
24 | }
25 |
26 | func stop() {
27 | eventEmitter.sendEvent(withName: EventName.messageStorage_stop, body: nil)
28 | }
29 |
30 | func insert(outgoing messages: [MMBaseMessage], completion: @escaping () -> Void) {
31 | // Implementation not needed. This method is intended for client usage.
32 | }
33 |
34 | func insert(incoming messages: [MMBaseMessage], completion: @escaping () -> Void) {
35 | eventEmitter.sendEvent(withName: EventName.messageStorage_save, body: messages.map({$0.dictionary()}))
36 | completion()
37 | }
38 |
39 | func findMessage(withId messageId: MessageId) -> MMBaseMessage? {
40 | queue.sync() {
41 | eventEmitter.sendEvent(withName: EventName.messageStorage_find, body: [messageId])
42 | _ = findSemaphore.wait(wallTimeout: DispatchWallTime.now() + DispatchTimeInterval.seconds(30))
43 | }
44 | return foundMessage
45 | }
46 |
47 | func update(messageSeenStatus status: MMSeenStatus, for messageId: MessageId, completion: @escaping () -> Void) {
48 | completion()
49 | // Implementation not needed. This method is intended for client usage.
50 | }
51 |
52 | func update(deliveryReportStatus isDelivered: Bool, for messageId: MessageId, completion: @escaping () -> Void) {
53 | completion()
54 | // Implementation not needed. This method is intended for client usage.
55 | }
56 |
57 | func update(messageSentStatus status: MM_MOMessageSentStatus, for messageId: MessageId, completion: @escaping () -> Void) {
58 | completion()
59 | // Implementation not needed. This method is intended for client usage.
60 | }
61 |
62 | func findAllMessageIds(completion: @escaping ([String]) -> Void) {
63 | // Implementation not needed. This method is intended for client usage.
64 | }
65 |
66 | /*
67 | Methods to provide results to Native Bridge.
68 | Called from JS part.
69 | */
70 |
71 | public func findResult(messageDict: [String: Any]?) {
72 | guard let messageDict = messageDict else {
73 | foundMessage = nil
74 | findSemaphore.signal()
75 | return
76 | }
77 |
78 | foundMessage = MMBaseMessage.createFrom(dictionary: messageDict)
79 | findSemaphore.signal()
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/ios/MobileMessagingPlugin/RNMobileMessagingUtils.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Utils.swift
3 | // infobip-mobile-messaging-react-native-plugin
4 | //
5 | // Created by Olga Koroleva on 04.02.2020.
6 | //
7 |
8 | import Foundation
9 | import MobileMessaging
10 |
11 | extension MM_MTMessage {
12 | override func dictionary() -> [String: Any] {
13 | var result = [String: Any]()
14 | result["messageId"] = messageId
15 | result["title"] = title
16 | result["body"] = text
17 | result["sound"] = sound
18 | result["silent"] = isSilent
19 | result["receivedTimestamp"] = UInt64(sendDateTime * 1000)
20 | result["customPayload"] = customPayload
21 | result["originalPayload"] = originalPayload
22 | result["contentUrl"] = contentUrl
23 | result["seen"] = seenStatus != .NotSeen
24 | result["seenDate"] = seenDate?.timeIntervalSince1970
25 | result["chat"] = isChatMessage
26 | result["browserUrl"] = browserUrl?.absoluteString
27 | result["deeplink"] = deeplink?.absoluteString
28 | result["webViewUrl"] = webViewUrl?.absoluteString
29 | result["inAppOpenTitle"] = inAppOpenTitle
30 | result["inAppDismissTitle"] = inAppDismissTitle
31 | return result
32 | }
33 |
34 | }
35 |
36 | extension MMInbox {
37 | func dictionary() -> [String: Any] {
38 | var result = [String: Any]()
39 | result["countTotal"] = countTotal
40 | result["countUnread"] = countUnread
41 | result["messages"] = messages.map({ return $0.dictionaryRepresentation })
42 | return result
43 | }
44 | }
45 |
46 | extension MMBaseMessage {
47 | class func createFrom(dictionary: [String: Any]) -> MMBaseMessage? {
48 | guard let messageId = dictionary["messageId"] as? String,
49 | let originalPayload = dictionary["originalPayload"] as? MMStringKeyPayload else
50 | {
51 | return nil
52 | }
53 |
54 | return MMBaseMessage(messageId: messageId, direction: MMMessageDirection.MT, originalPayload: originalPayload, deliveryMethod: .undefined)
55 | }
56 |
57 | func dictionary() -> [String: Any] {
58 | var result = [String: Any]()
59 | result["messageId"] = messageId
60 | result["customPayload"] = originalPayload["customPayload"]
61 | result["originalPayload"] = originalPayload
62 |
63 | if let aps = originalPayload["aps"] as? MMStringKeyPayload {
64 | result["body"] = aps["body"]
65 | result["sound"] = aps["sound"]
66 | }
67 |
68 | if let internalData = originalPayload["internalData"] as? MMStringKeyPayload,
69 | let _ = internalData["silent"] as? MMStringKeyPayload {
70 | result["silent"] = true
71 | } else if let silent = originalPayload["silent"] as? Bool {
72 | result["silent"] = silent
73 | }
74 |
75 | return result
76 | }
77 | }
78 |
79 | extension Optional {
80 | func unwrap(orDefault fallbackValue: T) -> T {
81 | switch self {
82 | case .some(let val as T):
83 | return val
84 | default:
85 | return fallbackValue
86 | }
87 | }
88 | }
89 |
90 | struct EventName {
91 | static let tokenReceived = "tokenReceived"
92 | static let registrationUpdated = "registrationUpdated"
93 | static let installationUpdated = "installationUpdated"
94 | static let userUpdated = "userUpdated"
95 | static let personalized = "personalized"
96 | static let depersonalized = "depersonalized"
97 | static let actionTapped = "actionTapped"
98 | static let notificationTapped = "notificationTapped"
99 | static let messageReceived = "messageReceived"
100 | static let messageStorage_start = "messageStorage.start"
101 | static let messageStorage_stop = "messageStorage.stop"
102 | static let messageStorage_save = "messageStorage.save"
103 | static let messageStorage_find = "messageStorage.find"
104 | static let messageStorage_findAll = "messageStorage.findAll"
105 | static let inAppChat_availabilityUpdated = "inAppChat.availabilityUpdated"
106 | static let inAppChat_unreadMessageCounterUpdated = "inAppChat.unreadMessageCounterUpdated"
107 | static let inAppChat_viewStateChanged = "inAppChat.viewStateChanged"
108 | static let inAppChat_configurationSynced = "inAppChat.configurationSynced"
109 | static let inAppChat_registrationIdUpdated = "inAppChat.livechatRegistrationIdUpdated"
110 | }
111 |
112 | extension UIApplication {
113 | class func topViewController(controller: UIViewController? = UIApplication.shared.firstKeyWindow?.rootViewController) -> UIViewController? {
114 | if let navigationController = controller as? UINavigationController {
115 | return topViewController(controller: navigationController.visibleViewController)
116 | }
117 | if let tabController = controller as? UITabBarController {
118 | if let selected = tabController.selectedViewController {
119 | return topViewController(controller: selected)
120 | }
121 | }
122 | if let presented = controller?.presentedViewController {
123 | return topViewController(controller: presented)
124 | }
125 | return controller
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/ios/ReactNativeMobileMessaging-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 |
5 | #import
6 | #import
7 | #import
8 |
--------------------------------------------------------------------------------
/newversion:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | if [ -z "$1" ]
4 | then
5 | echo "Please provide version as first paratemer"
6 | exit 1
7 | fi
8 |
9 | # Update version in plugin.xml
10 | #sed -E -e 'H;1h;$!d;x' -e 's@version\=\"[^"\s]*\"@version="'$1'"@' -i '' plugin.xml
11 |
12 | # Update version in package.json
13 | npm --no-git-tag-version --force version $1
14 |
15 | if [ -z "$2" ]
16 | then
17 | #git add plugin.xml
18 | git add package.json
19 | git add README.md
20 | else
21 | echo "Skipping 'git add'"
22 | fi
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "infobip-mobile-messaging-react-native-plugin",
3 | "title": "Infobip Mobile Messaging React Native Plugin",
4 | "version": "13.3.0",
5 | "description": "Infobip Mobile Messaging React Native Plugin",
6 | "main": "./src/index.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/infobip/mobile-messaging-react-native-plugin.git",
13 | "baseUrl": "https://github.com/infobip/mobile-messaging-react-native-plugin"
14 | },
15 | "keywords": [
16 | "react-native",
17 | "infobip",
18 | "push",
19 | "plugin",
20 | "messaging",
21 | "android",
22 | "ios"
23 | ],
24 | "author": {
25 | "name": "Infobip Mobile Messaging Team",
26 | "email": "push.support@infobip.com"
27 | },
28 | "license": "Apache-2.0",
29 | "readmeFilename": "README.md",
30 | "homepage": "https://github.com/infobip/mobile-messaging-react-native-plugin#readme",
31 | "bugs": {
32 | "url": "https://github.com/infobip/mobile-messaging-react-native-plugin/issues"
33 | },
34 | "peerDependencies": {
35 | "react": "^18.3.1",
36 | "react-native": ">=0.68.0 <1.0.x"
37 | },
38 | "devDependencies": {
39 | "metro-react-native-babel-preset": "^0.77.0",
40 | "react": "^18.3.1",
41 | "react-native": "^0.75.4"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | git remote rm github
4 |
5 | # Find last git tag and create commit log
6 | LAST_TAG=`git describe --tags --abbrev=0`
7 | RELEASE_COMMIT_LOG=`git log $LAST_TAG..HEAD --oneline`
8 |
9 | # Save commit log to property file as a property
10 | # (replacing newlines with "\n")
11 | echo RELEASE_COMMIT_LOG="${RELEASE_COMMIT_LOG//$'\n'/\\n}" > $PROPERTIES_FILE
12 |
13 | # Bump version
14 | ./newversion $RELEASE_VERSION
15 |
16 | # Remove package lock (temporary)
17 | rm -f package-lock.json
18 |
19 | git add .
20 |
21 | # Commit release version
22 | git commit -a -m "Release: $RELEASE_VERSION"
23 |
24 | # Create and push tag
25 | git tag $RELEASE_VERSION -m "Release: $RELEASE_VERSION"
26 |
27 | # Setting username and password for HTTPS to BitBucket
28 | encoded_username=$(echo ${GIT_USERNAME} | jq -Rr @uri)
29 | encoded_password=$(echo ${GIT_PASSWORD} | jq -Rr @uri)
30 | git remote set-url origin https://${encoded_username}:${encoded_password}@git.ib-ci.com/scm/mml/infobip-mobile-messaging-react-native-plugin.git
31 |
32 | # Push changes
33 | git push origin master --tags
34 |
--------------------------------------------------------------------------------
/src/components/RNMMChatViewNativeComponent.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import React, { FC, useLayoutEffect, useRef } from "react";
3 | import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
4 | import {findNodeHandle, requireNativeComponent} from 'react-native'
5 |
6 | interface RNMMChatViewProps {
7 | sendButtonColor: ?string
8 | }
9 |
10 | const RNMMChatViewCommands = codegenNativeCommands({
11 | supportedCommands: ["add", "remove"],
12 | });
13 |
14 | export const ChatView: FC = props => {
15 | const ref = useRef(null);
16 |
17 | useLayoutEffect(() => {
18 | // Not needed for iOS.
19 | if (Platform.OS === "ios") return;
20 |
21 | const chatViewRef = ref.current
22 | // Nothing to do if there is no chatView reference.
23 | if (!chatViewRef) return;
24 |
25 | let addedViewId: ?number = null
26 |
27 | // Fix for android, sometimes it can't get parent view, which is needed
28 | // for proper relayout.
29 | setTimeout(() => {
30 | const viewId = findNodeHandle(chatViewRef);
31 | if (viewId !== null && viewId !== undefined) {
32 | RNMMChatViewCommands.add(chatViewRef, viewId);
33 | console.log(`Adding android viewId: ${viewId}.`);
34 | addedViewId = viewId;
35 | }
36 | }, 100);
37 |
38 | return () => {
39 | const viewId = addedViewId
40 | if (viewId !== null && viewId !== undefined) {
41 | console.log(`Removing android viewId: ${viewId}.`);
42 | RNMMChatViewCommands.remove(chatViewRef, viewId);
43 | }
44 | };
45 | }, []);
46 |
47 | return ;
48 | };
49 |
50 | ChatView.propTypes = {
51 | /**
52 | * Send button color can be set in hex format.
53 | * If it's not provided, color from Infobip Portal widget configuration will be set.
54 | */
55 | sendButtonColor: PropTypes.string,
56 | };
57 |
58 | export const RNMMChatView = requireNativeComponent('RNMMChatView', ChatView);
59 |
--------------------------------------------------------------------------------