notifly-sdk 2.2.6 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +9 -26
  2. package/android/build.gradle +100 -0
  3. package/android/gradle.properties +5 -0
  4. package/android/src/main/AndroidManifest.xml +4 -0
  5. package/android/src/main/java/com/notiflysdk/NotiflySdkModule.kt +105 -0
  6. package/android/src/main/java/com/notiflysdk/NotiflySdkPackage.kt +35 -0
  7. package/android/src/newarch/NotiflySdkSpec.kt +7 -0
  8. package/android/src/oldarch/NotiflySdkSpec.kt +24 -0
  9. package/ios/NotiflySdk-Bridging-Header.h +2 -0
  10. package/ios/NotiflySdk.m +22 -0
  11. package/ios/NotiflySdk.swift +39 -0
  12. package/ios/NotiflySdk.xcodeproj/project.pbxproj +273 -0
  13. package/ios/NotiflySdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
  14. package/lib/commonjs/NativeNotiflySdk.js +10 -0
  15. package/lib/commonjs/NativeNotiflySdk.js.map +1 -0
  16. package/lib/commonjs/index.js +85 -0
  17. package/lib/commonjs/index.js.map +1 -0
  18. package/lib/commonjs/types.js +2 -0
  19. package/lib/commonjs/types.js.map +1 -0
  20. package/lib/module/NativeNotiflySdk.js +3 -0
  21. package/lib/module/NativeNotiflySdk.js.map +1 -0
  22. package/lib/module/index.js +70 -0
  23. package/lib/module/index.js.map +1 -0
  24. package/lib/module/types.js +2 -0
  25. package/lib/module/types.js.map +1 -0
  26. package/lib/typescript/NativeNotiflySdk.d.ts +15 -0
  27. package/lib/typescript/NativeNotiflySdk.d.ts.map +1 -0
  28. package/lib/typescript/index.d.ts +26 -0
  29. package/lib/typescript/index.d.ts.map +1 -0
  30. package/lib/typescript/types.d.ts +7 -0
  31. package/lib/typescript/types.d.ts.map +1 -0
  32. package/notifly_react_native_sdk.podspec +36 -0
  33. package/package.json +158 -28
  34. package/src/NativeNotiflySdk.ts +25 -0
  35. package/src/index.tsx +105 -0
  36. package/src/types.ts +7 -0
  37. package/.eslintrc.cjs +0 -40
  38. package/.prettierrc.yml +0 -14
  39. package/index.js +0 -190
  40. package/src/auth.js +0 -42
  41. package/src/constant.js +0 -8
  42. package/src/in_app_message.js +0 -258
  43. package/src/log_event.js +0 -185
  44. package/src/user.js +0 -51
  45. package/src/utils.js +0 -145
package/.eslintrc.cjs DELETED
@@ -1,40 +0,0 @@
1
- module.exports = {
2
- root: true,
3
- env: {
4
- es6: true,
5
- jest: true,
6
- node: true,
7
- 'react-native/react-native': true,
8
- },
9
- parser: '@babel/eslint-parser',
10
- plugins: ['react', 'react-native'],
11
- extends: ['eslint:recommended', 'plugin:react/recommended'],
12
- rules: {
13
- 'react/prop-types': 'off',
14
- 'react/react-in-jsx-scope': 'off',
15
- 'no-console': 'off',
16
- 'no-unused-vars': 'warn',
17
- 'react-native/no-unused-styles': 'warn',
18
- 'react-native/split-platform-components': 'warn',
19
- 'react-native/no-inline-styles': 'warn',
20
- 'react-native/no-color-literals': 'warn',
21
- 'react-native/no-raw-text': 'warn',
22
- },
23
- settings: {
24
- react: {
25
- version: 'detect',
26
- },
27
- },
28
- parserOptions: {
29
- requireConfigFile: false,
30
- ecmaVersion: 2021,
31
- sourceType: 'module',
32
- ecmaFeatures: {
33
- jsx: true,
34
- },
35
- babelOptions: {
36
- presets: ['@babel/preset-env', '@babel/preset-react'],
37
- plugins: ['@babel/plugin-syntax-import-assertions'],
38
- },
39
- },
40
- };
package/.prettierrc.yml DELETED
@@ -1,14 +0,0 @@
1
- # .prettierrc or .prettierrc.yaml
2
- proseWrap: 'preserve'
3
- trailingComma: 'es5'
4
- tabWidth: 4
5
- semi: true
6
- singleQuote: true
7
- quoteProps: 'preserve'
8
- printWidth: 120
9
- overrides:
10
- - files:
11
- - '*.json'
12
- - '*.yml'
13
- options:
14
- tabWidth: 2
package/index.js DELETED
@@ -1,190 +0,0 @@
1
- import { Linking } from 'react-native';
2
- import RootSiblings from 'react-native-root-siblings';
3
- import AsyncStorage from '@react-native-async-storage/async-storage';
4
- import messaging from '@react-native-firebase/messaging';
5
- import logEvent from './src/log_event';
6
- import { setUserProperties, removeUserId } from './src/user';
7
- import { base64Decode, clickHandler, sessionStart } from './src/utils';
8
- import { showInAppMessage } from './src/in_app_message';
9
- let isSetBackgroundHandler = false;
10
- let isNotiflyInitialized = false;
11
- const openedInAppWebViewCount = { count: 0 };
12
-
13
- exports.trackEvent = logEvent;
14
- exports.setUserProperties = setUserProperties;
15
- exports.clickHandler = clickHandler;
16
-
17
- /**
18
- * Sets the background message handler for the Notifly SDK.
19
- * This method should be called in the index.js file of your app.
20
- * Should be used when you don't have a custom background message handler.
21
- * @returns {Promise<void>} - A promise that resolves when the background message handler is set.
22
- * @example
23
- * setNotiflyBackgroundMessageHandler();
24
- */
25
- async function setNotiflyBackgroundMessageHandler() {
26
- messaging().setBackgroundMessageHandler(notiflyBackgroundHandler);
27
- }
28
-
29
- /**
30
- * The background message handler for the Notifly SDK.
31
- * This method should be called in the index.js file of your app.
32
- * Should be used when you have a custom background message handler.
33
- * @param {Object} remoteMessage - The remote message to handle.
34
- * @returns {Promise<void>} - A promise that resolves when the background message handler is set.
35
- * @example
36
- * messaging().setBackgroundMessageHandler(async remoteMessage => {
37
- console.log('Existing handler: Background message received:', remoteMessage);
38
- await notiflyBackgroundHandler(remoteMessage);
39
- });
40
- */
41
- async function notiflyBackgroundHandler(remoteMessage) {
42
- if (!remoteMessage.notification) {
43
- return; // TODO(minyong): Discuss if we should log only when notifly_message_type is push-notitification.
44
- }
45
- if (!isSetBackgroundHandler) {
46
- await logEvent(
47
- 'push_delivered',
48
- {
49
- type: 'message_event',
50
- channel: 'push-notification',
51
- campaign_id: remoteMessage?.data?.campaign_id,
52
- notifly_message_id: remoteMessage?.data?.notifly_message_id,
53
- status: 'quit',
54
- },
55
- null,
56
- true,
57
- );
58
- isSetBackgroundHandler = true;
59
- return;
60
- }
61
- await logEvent(
62
- 'push_delivered',
63
- {
64
- type: 'message_event',
65
- channel: 'push-notification',
66
- campaign_id: remoteMessage?.data?.campaign_id,
67
- notifly_message_id: remoteMessage.data?.notifly_message_id,
68
- status: 'background',
69
- },
70
- null,
71
- true,
72
- );
73
- }
74
-
75
- /**
76
- * Sets the external user ID for the user.
77
- *
78
- * @async
79
- * @param {string} userID - The external user ID for the user.
80
- * @returns {Promise<void>} - A promise that resolves when the user ID is set.
81
- *
82
- * @example
83
- * await setUserId('123456789');
84
- */
85
- exports.setUserId = async function (userID) {
86
- try {
87
- if (userID) {
88
- await setUserProperties({
89
- external_user_id: userID,
90
- });
91
- return;
92
- }
93
- await removeUserId();
94
- return;
95
- } catch (err) {
96
- console.warn('[Notifly] setUserId failed.');
97
- }
98
- };
99
-
100
- /**
101
- * Initializes the Notifly SDK with the given project ID, user name, and password.
102
- *
103
- * @async
104
- * @param {string} prjId - The project ID to use for initialization.
105
- * @param {string} userName - The user name to use for authentication.
106
- * @param {string} password - The password to use for authentication.
107
- * @param {boolean} [useCustomClickHandler=false] - A flag indicating whether to use a custom click handler for push notifications.
108
- * @returns {Promise<void>} A promise that resolves when initialization is complete, or rejects with an error.
109
- *
110
- * @example
111
- * await initialize('myProjectId', 'myUserName', 'myPassword');
112
- */
113
- exports.initialize = async function (prjId, userName, password, useCustomClickHandler = false) {
114
- if (isNotiflyInitialized) {
115
- return;
116
- }
117
- try {
118
- await messaging().requestPermission();
119
- // in-app-message
120
- messaging().onMessage((remoteMessage) => {
121
- new RootSiblings(null).destroy();
122
- handleInAppMessage(remoteMessage, openedInAppWebViewCount);
123
- });
124
-
125
-
126
- messaging().onNotificationOpenedApp(handleNotificationOpened);
127
-
128
- // custom push click handler
129
- if (!useCustomClickHandler) {
130
- const initialNotification = await messaging().getInitialNotification();
131
- if (initialNotification) {
132
- await clickHandler(initialNotification);
133
- }
134
- }
135
-
136
- messaging().getToken();
137
- messaging().setDeliveryMetricsExportToBigQuery(true);
138
-
139
- await Promise.all([
140
- AsyncStorage.setItem('notiflyProjectId', prjId),
141
- AsyncStorage.setItem('notiflyUserName', userName),
142
- AsyncStorage.setItem('notiflyUserPassword', password),
143
- ]);
144
- await sessionStart();
145
- isNotiflyInitialized = true;
146
- } catch (err) {
147
- console.warn('[Notifly]: ', err);
148
- }
149
- };
150
-
151
- async function handleInAppMessage(remoteMessage, openedInAppWebViewCount) {
152
- try {
153
- if (remoteMessage.data?.notifly_message_type === 'in-app-message' && remoteMessage.data?.notifly_in_app_message_data) {
154
- const decodedJsonString = base64Decode(remoteMessage.data?.notifly_in_app_message_data);
155
- const notiflyInAppMessageData = JSON.parse(decodedJsonString);
156
- showInAppMessage(notiflyInAppMessageData, openedInAppWebViewCount);
157
- }
158
- } catch (err) {
159
- console.warn('[Notifly] In-app message handling failed:', err);
160
- }
161
- }
162
-
163
- async function handleNotificationOpened(remoteMessage) {
164
- try {
165
- if (remoteMessage.data?.notifly_message_type != 'push-notification') {
166
- return;
167
- }
168
- const link = remoteMessage.data?.link;
169
- if (link) {
170
- Linking.openURL(link);
171
- }
172
- await logEvent(
173
- 'push_click',
174
- {
175
- type: 'message_event',
176
- channel: 'push-notification',
177
- campaign_id: remoteMessage.data.campaign_id,
178
- notifly_message_id: remoteMessage.data?.notifly_message_id,
179
- status: 'background',
180
- },
181
- null,
182
- true
183
- );
184
- } catch (err) {
185
- console.warn('[Notifly] Notification opened handling failed:', err);
186
- }
187
- }
188
-
189
- exports.setNotiflyBackgroundMessageHandler = setNotiflyBackgroundMessageHandler;
190
- exports.notiflyBackgroundHandler = notiflyBackgroundHandler;
package/src/auth.js DELETED
@@ -1,42 +0,0 @@
1
- /**
2
- * Fetches a Cognito ID token for the given user name and password.
3
- *
4
- * @async
5
- * @param {string} userName - The user name to use for authentication.
6
- * @param {string} password - The password to use for authentication.
7
- * @returns {Promise<string>} A promise that resolves with the Cognito ID token, or rejects with an error.
8
- *
9
- * @example
10
- * const token = await getCognitoIdToken('myUserName', 'myPassword');
11
- */
12
- export async function getCognitoIdToken(userName, password) {
13
- const headers = new Headers({
14
- 'X-Amz-Target': 'AWSCognitoIdentityProviderService.InitiateAuth',
15
- 'Content-Type': 'application/x-amz-json-1.1',
16
- });
17
-
18
- const body = JSON.stringify({
19
- AuthFlow: 'USER_PASSWORD_AUTH',
20
- AuthParameters: {
21
- PASSWORD: password,
22
- USERNAME: userName,
23
- },
24
- ClientId: '2pc5pce21ec53csf8chafknqve',
25
- });
26
-
27
- const requestOptions = {
28
- method: 'POST',
29
- headers,
30
- body,
31
- redirect: 'follow',
32
- };
33
-
34
- try {
35
- const response = await fetch('https://cognito-idp.ap-northeast-2.amazonaws.com/', requestOptions);
36
- const result = await response.text();
37
- const token = JSON.parse(result).AuthenticationResult.IdToken;
38
- return token;
39
- } catch (error) {
40
- console.warn('[Notifly]: ', error);
41
- }
42
- }
package/src/constant.js DELETED
@@ -1,8 +0,0 @@
1
- export const SDK_VERSION = '2.2.6';
2
-
3
- export const NAMESPACE = {
4
- 'EVENTID': '830b5f7b-e392-43db-a17b-d835f0bcab2b',
5
- 'REGISTERED_USERID': 'ce7c62f9-e8ae-4009-8fd6-468e9581fa21',
6
- 'UNREGISTERED_USERID': 'a6446dcf-c057-4de7-a360-56af8659d52f',
7
- 'DEVICEID': '830848b3-2444-467d-9cd8-3430d2738c57',
8
- };
@@ -1,258 +0,0 @@
1
- import React from 'react';
2
- import { View, Linking, Dimensions } from 'react-native';
3
- import RootSiblings from 'react-native-root-siblings';
4
- import Modal from 'react-native-modal';
5
- import WebView from 'react-native-webview';
6
- import logEvent from './log_event';
7
- import { setUserProperties } from './user';
8
-
9
- /**
10
- * Displays an in-app message in a modal WebView.
11
- *
12
- * @async
13
- * @param {Object} data - An object containing information about the in-app message to display.
14
- * @param {Object} openedInAppWebViewCount - An object containing the count of opened in-app web views.
15
- * @returns {Promise<void>} A promise that resolves when the in-app message has been displayed, or rejects with an error.
16
- *
17
- * @example
18
- * const data = { campaign_id: 'myCampaign', url: 'https://example.com' };
19
- * const openedInAppWebViewCount = { count: 0 };
20
- * await showInAppMessage(data, openedInAppWebViewCount);
21
- */
22
- export async function showInAppMessage(data, openedInAppWebViewCount) {
23
- if (openedInAppWebViewCount.count > 0) {
24
- return;
25
- }
26
- if (!(data?.url && data?.modal_properties)) {
27
- return;
28
- }
29
- const modalProperties = data.modal_properties || {};
30
- const screenWidth = Dimensions.get('window').width;
31
- const screenHeight = Dimensions.get('window').height;
32
- const webViewProps = _translateWebviewProps(modalProperties, screenWidth, screenHeight);
33
- const link = data.url; // default html link for only testing.
34
- const injectedJavaScript = `
35
- const button_trigger = document.getElementById('notifly-button-trigger');
36
- button_trigger.addEventListener('click', function(event){
37
- if (!event.notifly_button_click_type) return;
38
- window.ReactNativeWebView.postMessage(JSON.stringify({
39
- type: event.notifly_button_click_type,
40
- button_name: event.notifly_button_name,
41
- link: event.notifly_button_click_link,
42
- extra_data: event.notifly_extra_data,
43
- }));
44
- });
45
- `;
46
- const backdropOpacity = _getBackgroundOpacity(modalProperties?.backgroundOpacity);
47
-
48
- const webviewMessageHandler = (e) => {
49
- const message = JSON.parse(e.nativeEvent.data);
50
- if (message.type === 'close') {
51
- modal.destroy();
52
- openedInAppWebViewCount.count = openedInAppWebViewCount.count - 1;
53
- logEvent(
54
- 'close_button_click',
55
- {
56
- type: 'message_event',
57
- channel: 'in-app-message',
58
- button_name: message.button_name,
59
- campaign_id: data.campaign_id,
60
- notifly_message_id: data.notifly_message_id,
61
- },
62
- null,
63
- true
64
- );
65
- } else if (message.type === 'main_button') {
66
- logEvent(
67
- 'main_button_click',
68
- {
69
- type: 'message_event',
70
- channel: 'in-app-message',
71
- button_name: message.button_name,
72
- campaign_id: data.campaign_id,
73
- notifly_message_id: data.notifly_message_id,
74
- },
75
- null,
76
- true
77
- );
78
- if (message.link) {
79
- modal.destroy();
80
- openedInAppWebViewCount.count = openedInAppWebViewCount.count - 1;
81
- Linking.openURL(message.link);
82
- }
83
- } else if (message.type === 'hide_in_app_message') {
84
- modal.destroy();
85
- openedInAppWebViewCount.count = openedInAppWebViewCount.count - 1;
86
- logEvent(
87
- 'hide_in_app_message_button_click',
88
- {
89
- type: 'message_event',
90
- channel: 'in-app-message',
91
- button_name: message.button_name,
92
- campaign_id: data.campaign_id,
93
- notifly_message_id: data.notifly_message_id,
94
- },
95
- null,
96
- true
97
- );
98
- if (modalProperties.template_name) {
99
- const key = `hide_in_app_message_${modalProperties.template_name}`;
100
- setUserProperties({
101
- [key]: true,
102
- });
103
- }
104
- } else if (message.type === 'survey_submit_button') {
105
- modal.destroy();
106
- openedInAppWebViewCount.count = openedInAppWebViewCount.count - 1;
107
- logEvent(
108
- 'survey_submit_button_click', {
109
- type: 'message_event',
110
- channel: 'in-app-message',
111
- button_name: message.button_name,
112
- campaign_id: data.campaign_id,
113
- notifly_message_id: data.notifly_message_id,
114
- notifly_extra_data: message.extra_data,
115
- },
116
- null,
117
- true
118
- );
119
- }
120
- };
121
-
122
- openedInAppWebViewCount.count = openedInAppWebViewCount.count + 1;
123
- logEvent(
124
- 'in_app_message_show',
125
- { type: 'message_event', channel: 'in-app-message', campaign_id: data.campaign_id, notifly_message_id: data.notifly_message_id },
126
- null,
127
- true
128
- ); // logging in app messaging delivered
129
- const modal = new RootSiblings(
130
- (
131
- <Modal
132
- isVisible={true}
133
- transparent={true}
134
- onBackdropPress={() => {
135
- openedInAppWebViewCount.count = openedInAppWebViewCount.count - 1;
136
- modal.destroy();
137
- }}
138
- onBackButtonPress={() => {
139
- openedInAppWebViewCount.count = openedInAppWebViewCount.count - 1;
140
- modal.destroy();
141
- }}
142
- backdropOpacity={backdropOpacity}
143
- style={webViewProps.modalStyle}
144
- >
145
- <View>
146
- <View style={webViewProps.viewStyle}>
147
- <WebView
148
- originWhitelist={['*']}
149
- source={{
150
- uri: link,
151
- }}
152
- style={{
153
- width: screenWidth,
154
- height: screenHeight,
155
- }}
156
- onMessage={webviewMessageHandler}
157
- javaScriptEnabled={true}
158
- injectedJavaScript={injectedJavaScript}
159
- />
160
- </View>
161
- </View>
162
- </Modal>
163
- )
164
- );
165
- }
166
-
167
- function _translateWebviewProps(modalProps, screenWidth, screenHeight) {
168
- const modalStyle = {
169
- margin: 0,
170
- justifyContent: 'center',
171
- alignItems: 'center',
172
- ...(modalProps?.position === 'bottom' && {
173
- position: 'absolute',
174
- bottom: 0,
175
- }),
176
- };
177
-
178
- const viewStyle = {
179
- borderTopLeftRadius: modalProps?.borderTopLeftRadius || 0,
180
- borderTopRightRadius: modalProps?.borderTopRightRadius || 0,
181
- borderBottomLeftRadius: modalProps?.borderBottomLeftRadius || 0,
182
- borderBottomRightRadius: modalProps?.borderBottomRightRadius || 0,
183
- overflow: 'hidden',
184
- width: _getViewWidth(modalProps, screenWidth, screenHeight),
185
- height: _getViewHeight(modalProps, screenWidth, screenHeight),
186
- justifyContent: 'center',
187
- alignItems: 'center',
188
- };
189
-
190
- return {
191
- modalStyle,
192
- viewStyle,
193
- };
194
- }
195
-
196
- function _getViewWidth(modalProps, screenWidth, screenHeight) {
197
- let viewWidth;
198
-
199
- if (modalProps.width) {
200
- viewWidth = modalProps.width;
201
- } else if (!screenWidth) {
202
- console.error('screenWidth is not defined');
203
- viewWidth = '100%';
204
- } else if (modalProps.width_vw) {
205
- viewWidth = screenWidth * (modalProps.width_vw / 100);
206
- } else if (modalProps.width_vh && screenHeight) {
207
- viewWidth = screenHeight * (modalProps.width_vh / 100);
208
- } else {
209
- viewWidth = '100%';
210
- }
211
-
212
- if (modalProps.min_width && viewWidth < modalProps.min_width) {
213
- viewWidth = modalProps.minWidth;
214
- }
215
- if (modalProps.max_width && viewWidth > modalProps.max_width) {
216
- viewWidth = modalProps.maxWidth;
217
- }
218
-
219
- return viewWidth;
220
- }
221
-
222
- function _getViewHeight(modalProps, screenWidth, screenHeight) {
223
- let viewHeight;
224
-
225
- if (modalProps.height) {
226
- viewHeight = modalProps.height;
227
- } else if (!screenHeight) {
228
- console.error('screenHeight is not defined');
229
- viewHeight = '100%';
230
- } else if (modalProps.height_vh) {
231
- viewHeight = screenHeight * (modalProps.height_vh / 100);
232
- } else if (modalProps.height_vw && screenWidth) {
233
- viewHeight = screenWidth * (modalProps.height_vw / 100);
234
- } else {
235
- viewHeight = '100%';
236
- }
237
-
238
- if (modalProps.min_height && viewHeight < modalProps.min_height) {
239
- viewHeight = modalProps.min_height;
240
- }
241
- if (modalProps.max_height && viewHeight > modalProps.max_height) {
242
- viewHeight = modalProps.max_height;
243
- }
244
-
245
- return viewHeight;
246
- }
247
-
248
- function _getBackgroundOpacity(backgroundOpacity) {
249
- // if backgroundOpacity is not defined, default value is 0.2
250
- if (backgroundOpacity === undefined) {
251
- return 0.2;
252
- }
253
- // if backgroundOpacity is not between 0 and 1, default value is 0.2
254
- if (backgroundOpacity < 0 || backgroundOpacity > 1) {
255
- return 0.2;
256
- }
257
- return backgroundOpacity;
258
- }