@inngageregistry/inngage-react 4.0.0-beta.1 → 4.0.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 (43) hide show
  1. package/README.md +61 -40
  2. package/dist/Inngage.d.ts +28 -0
  3. package/dist/Inngage.js +149 -0
  4. package/dist/api/api.d.ts +4 -0
  5. package/{src/api/api.ts → dist/api/api.js} +22 -28
  6. package/dist/api/handler.d.ts +1 -0
  7. package/dist/api/handler.js +44 -0
  8. package/dist/components/in_app.d.ts +6 -0
  9. package/dist/components/in_app.js +92 -0
  10. package/dist/components/modal.d.ts +26 -0
  11. package/dist/components/modal.js +158 -0
  12. package/dist/components/styles.d.ts +88 -0
  13. package/dist/components/styles.js +86 -0
  14. package/dist/firebase/notifications_listener.d.ts +6 -0
  15. package/dist/firebase/notifications_listener.js +170 -0
  16. package/dist/index.d.ts +6 -0
  17. package/dist/index.js +6 -0
  18. package/dist/models/inngage_properties.d.ts +11 -0
  19. package/dist/models/inngage_properties.js +13 -0
  20. package/dist/models/requests.d.ts +40 -0
  21. package/{src/models/requests.ts → dist/models/requests.js} +40 -42
  22. package/dist/services/api_services.d.ts +7 -0
  23. package/{src/services/api_services.ts → dist/services/api_services.js} +25 -30
  24. package/dist/services/handler.d.ts +1 -0
  25. package/dist/services/handler.js +38 -0
  26. package/dist/services/inngage.d.ts +4 -0
  27. package/dist/services/inngage.js +22 -0
  28. package/dist/utils.d.ts +4 -0
  29. package/dist/utils.js +25 -0
  30. package/package.json +79 -40
  31. package/.editorconfig +0 -6
  32. package/src/Inngage.ts +0 -193
  33. package/src/api/handler.ts +0 -53
  34. package/src/components/in_app.tsx +0 -159
  35. package/src/components/modal.tsx +0 -221
  36. package/src/components/styles.ts +0 -70
  37. package/src/firebase/notifications_listener.ts +0 -146
  38. package/src/index.ts +0 -8
  39. package/src/models/inngage_properties.ts +0 -13
  40. package/src/services/handler.ts +0 -41
  41. package/src/services/inngage.ts +0 -23
  42. package/src/utils.ts +0 -35
  43. package/tsconfig.json +0 -27
package/dist/utils.js ADDED
@@ -0,0 +1,25 @@
1
+ import { Alert } from 'react-native';
2
+ export const formatDate = (timestamp) => {
3
+ if (!timestamp) {
4
+ return null;
5
+ }
6
+ return new Date(timestamp).toISOString();
7
+ };
8
+ export const showAlert = (title, body) => {
9
+ Alert.alert(title, body, [{ text: 'OK', onPress: () => console.log('OK Pressed') }], {
10
+ cancelable: false,
11
+ });
12
+ };
13
+ export const showAlertLink = (title, body, appName, link) => {
14
+ return new Promise((resolve) => {
15
+ Alert.alert(title, `${body}\n\n${link}`, [{ text: 'NO', onPress: () => resolve(false) }, { text: 'OK', onPress: () => resolve(true) }], { cancelable: false });
16
+ });
17
+ };
18
+ export const isEmpty = (obj) => {
19
+ for (var prop in obj) {
20
+ if (obj.hasOwnProperty(prop)) {
21
+ return false;
22
+ }
23
+ }
24
+ return JSON.stringify(obj) === JSON.stringify({});
25
+ };
package/package.json CHANGED
@@ -1,41 +1,80 @@
1
- {
2
- "name": "@inngageregistry/inngage-react",
3
- "version": "4.0.0-beta.1",
4
- "description": "Inngage Plugin for React Native applications for marketing campaign optimization using Push Notification.",
5
- "main": "src/index.ts",
6
- "types": "src/index.d.ts",
7
- "scripts": {
8
- "test": "echo \"Error: no test specified\" && exit 1",
9
- "build": "npx tsc"
10
- },
11
- "author": "Inngage Developer",
12
- "license": "ISC",
13
- "repository": {
14
- "type": "git",
15
- "url": "git+https://github.com/inngage/inngage-react.git"
16
- },
17
- "bugs": {
18
- "url": "https://github.com/inngage/inngage-react/issues"
19
- },
20
- "homepage": "https://github.com/inngage/inngage-react#readme",
21
- "dependencies": {
22
- "@react-native-async-storage/async-storage": "^1.18.1",
23
- "@react-native-community/push-notification-ios": "^1.11.0",
24
- "@react-native-firebase/app": "^17.4.2",
25
- "@react-native-firebase/messaging": "^17.4.2",
26
- "react-native-device-info": "^10.6.0",
27
- "react-native-inappbrowser-reborn": "^3.7.0",
28
- "react-native-localize": "^2.2.6",
29
- "react-native-permissions": "^3.8.0",
30
- "react-native-push-notification": "^8.1.1",
31
- "react-native-snap-carousel": "^3.9.1"
32
- },
33
- "devDependencies": {
34
- "@types/jest": "^29.5.1",
35
- "@types/react": "^18.2.0",
36
- "@types/react-native": "^0.71.6",
37
- "@types/react-native-push-notification": "^8.1.1",
38
- "@types/react-test-renderer": "^18.0.0",
39
- "typescript": "^5.0.4"
40
- }
1
+ {
2
+ "name": "@inngageregistry/inngage-react",
3
+ "version": "4.0.0",
4
+ "description": "Inngage Plugin for React Native applications for marketing campaign optimization using Push Notification.",
5
+ "author": "Inngage Developer",
6
+ "license": "ISC",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/inngage/inngage-react.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/inngage/inngage-react/issues"
13
+ },
14
+ "homepage": "https://github.com/inngage/inngage-react#readme",
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "main": "dist/index.js",
19
+ "react-native": "dist/index.js",
20
+ "types": "dist/index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "react-native": "./dist/index.js",
25
+ "default": "./dist/index.js"
26
+ }
27
+ },
28
+ "sideEffects": false,
29
+ "scripts": {
30
+ "clean": "rimraf dist",
31
+ "build": "npm run clean && tsc -p tsconfig.build.json",
32
+ "prepare": "npm run build",
33
+ "test": "echo \"No tests yet\" && exit 0"
34
+ },
35
+ "dependencies": {},
36
+ "peerDependencies": {
37
+ "@notifee/react-native": ">=7 <10",
38
+ "@react-native-async-storage/async-storage": ">=2.1.0 <3",
39
+ "@react-native-firebase/app": ">=20.0.0 <24",
40
+ "@react-native-firebase/messaging": ">=20.0.0 <24",
41
+ "react": ">=18.2.0 <20",
42
+ "react-native": ">=0.72.0 <0.83.0",
43
+ "react-native-device-info": ">=10.0.0 <15",
44
+ "react-native-inappbrowser-reborn": ">=3.0.0 <4",
45
+ "react-native-localize": ">=3.0.0 <4",
46
+ "react-native-permissions": ">=5.0.0 <6"
47
+ },
48
+ "peerDependenciesMeta": {
49
+ "@react-native-async-storage/async-storage": {
50
+ "optional": true
51
+ },
52
+ "@react-native-firebase/app": {
53
+ "optional": true
54
+ },
55
+ "@react-native-firebase/messaging": {
56
+ "optional": true
57
+ },
58
+ "react-native-device-info": {
59
+ "optional": true
60
+ },
61
+ "react-native-inappbrowser-reborn": {
62
+ "optional": true
63
+ },
64
+ "react-native-localize": {
65
+ "optional": true
66
+ },
67
+ "react-native-permissions": {
68
+ "optional": true
69
+ },
70
+ "@notifee/react-native": {
71
+ "optional": true
72
+ }
73
+ },
74
+ "devDependencies": {
75
+ "@types/react": "^19.2.2",
76
+ "@types/react-test-renderer": "^19.0.0",
77
+ "rimraf": "^6.0.0",
78
+ "typescript": "^5.6.0"
79
+ }
41
80
  }
package/.editorconfig DELETED
@@ -1,6 +0,0 @@
1
- [*]
2
- end_of_line = lf
3
- insert_final_newline = true
4
- charset = utf-8
5
- indent_style = space
6
- indent_size = 2
package/src/Inngage.ts DELETED
@@ -1,193 +0,0 @@
1
- import { firebase } from '@react-native-firebase/messaging';
2
- import DeviceInfo from "react-native-device-info";
3
- import * as RNLocalize from "react-native-localize";
4
- import AsyncStorage from '@react-native-async-storage/async-storage';
5
-
6
- import { formatDate } from "./utils";
7
- import { InngageNotificationMessage, messagingHeadlessTask } from "./firebase/notifications_listener";
8
- import { InngageProperties } from './models/inngage_properties';
9
-
10
- import RNPermissions, { NotificationOption, RESULTS } from 'react-native-permissions';
11
-
12
- import ApiService from './services/api_services';
13
-
14
- const API_LEVEL_33 = 33;
15
-
16
- // --- Get Firebase Access ------/
17
- const getFirebaseAccess = async () => {
18
- return await handleNotificationsPermission();
19
- };
20
-
21
- const handleNotificationsPermission = async () => {
22
- const options: NotificationOption[] = ['alert', 'badge', 'sound'];
23
- const apiLevel = await DeviceInfo.getApiLevel();
24
-
25
- const permissionGranted =
26
- apiLevel >= API_LEVEL_33
27
- ? (await RNPermissions.requestNotifications(options)).status === RESULTS.GRANTED
28
- : (await firebase.messaging().requestPermission()) ===
29
- firebase.messaging.AuthorizationStatus.AUTHORIZED ||
30
- firebase.messaging.AuthorizationStatus.PROVISIONAL;
31
-
32
- if (permissionGranted) {
33
- return await getFirebaseToken();
34
- }
35
-
36
- throw new Error('Notification permission not granted');
37
- };
38
-
39
- const getFirebaseToken = async () => {
40
- let fcmToken = await AsyncStorage.getItem('fcmToken');
41
-
42
- if (!fcmToken) {
43
- if (!firebase.messaging().isDeviceRegisteredForRemoteMessages) {
44
- await firebase.messaging().registerDeviceForRemoteMessages?.();
45
- }
46
-
47
- const newFcmToken = await firebase.messaging().getToken?.();
48
-
49
- if (newFcmToken) {
50
- await AsyncStorage.setItem('fcmToken', newFcmToken);
51
- return newFcmToken;
52
- }
53
- }
54
-
55
- return fcmToken || null;
56
- };
57
-
58
- interface SubscriptionProps {
59
- appToken: string,
60
- dev?: boolean,
61
- friendlyIdentifier?: string,
62
- customFields?: any,
63
- customData?: any,
64
- phoneNumber?: string,
65
- email?: string
66
- }
67
-
68
- interface SendEventProps {
69
- eventName: string,
70
- conversionEvent?: boolean,
71
- conversionValue?: number,
72
- conversionNotId?: string,
73
- eventValues?: any
74
- }
75
-
76
- class Inngage {
77
- private static instance: Inngage;
78
- private apiService: ApiService;
79
-
80
- constructor() {
81
- this.apiService = new ApiService();
82
- }
83
-
84
- static getInstance(): Inngage {
85
- if (!Inngage.instance) {
86
- Inngage.instance = new Inngage();
87
- }
88
-
89
- return Inngage.instance;
90
- }
91
-
92
- static notificationListener(firebaseListenCallback?: any) {
93
- try {
94
- InngageNotificationMessage(firebaseListenCallback)
95
- } catch (e) {
96
- console.log(e)
97
- }
98
- }
99
-
100
- static async subscribe({
101
- appToken,
102
- friendlyIdentifier,
103
- customFields,
104
- phoneNumber,
105
- email,
106
- }: SubscriptionProps) {
107
- const inngage = Inngage.getInstance();
108
-
109
- InngageProperties.appToken = appToken;
110
- InngageProperties.identifier = friendlyIdentifier!;
111
-
112
- const respToken = await getFirebaseAccess();
113
-
114
- const { countryCode: osLocale, languageCode: osLanguage } = RNLocalize.getLocales()[0] || {};
115
- const deviceManufacturer = await DeviceInfo.getManufacturer();
116
- const installTime = await DeviceInfo.getFirstInstallTime();
117
- const lastUpdateTime = await DeviceInfo.getLastUpdateTime();
118
- const uuid = await DeviceInfo.getUniqueId();
119
- const appInstalledIn = formatDate(installTime);
120
- const appUpdatedIn = formatDate(lastUpdateTime);
121
-
122
- const subscription = {
123
- registerSubscriberRequest: {
124
- app_token: appToken,
125
- identifier: friendlyIdentifier,
126
- registration: respToken,
127
- platform: DeviceInfo.getSystemName(),
128
- sdk: DeviceInfo.getBuildNumber(),
129
- deviceModel: DeviceInfo.getModel(),
130
- deviceManufacturer,
131
- osLocale,
132
- osLanguage,
133
- os_version: DeviceInfo.getReadableVersion(),
134
- app_version: DeviceInfo.getBuildNumber(),
135
- appInstalledIn,
136
- appUpdatedIn,
137
- uuid,
138
- phone_Number: phoneNumber,
139
- email: email,
140
- customFields: customFields,
141
- }
142
- }
143
-
144
- return inngage.apiService.subscribe(subscription);
145
- }
146
-
147
- static async sendEvent({
148
- eventName,
149
- conversionEvent = false,
150
- conversionValue = 0,
151
- conversionNotId = "",
152
- eventValues,
153
- }: SendEventProps) {
154
- const inngage = Inngage.getInstance();
155
-
156
- const registration = await getFirebaseAccess();
157
-
158
- const request = {
159
- newEventRequest: {
160
- appToken: InngageProperties.appToken,
161
- identifier: InngageProperties.identifier,
162
- registration,
163
- eventName,
164
- conversionEvent,
165
- conversionValue,
166
- conversionNotId,
167
- eventValues,
168
- },
169
- };
170
-
171
- return inngage.apiService.sendEvent(request);
172
- }
173
-
174
- static async addUserData(customFields: any): Promise<any> {
175
- const inngage = Inngage.getInstance();
176
-
177
- const request = {
178
- fieldsRequest: {
179
- appToken: InngageProperties.appToken,
180
- identifier: InngageProperties.identifier,
181
- customField: customFields,
182
- },
183
- };
184
-
185
- return inngage.apiService.addUserData(request);
186
- }
187
-
188
- static setDebugMode(value: boolean) {
189
- InngageProperties.debugMode = value;
190
- }
191
- }
192
-
193
- export default Inngage;
@@ -1,53 +0,0 @@
1
- const baseUrlHook = {
2
- [false as any]: 'https://api.inngage.com.br/v1',
3
- [undefined as any]: 'https://api.inngage.com.br/v1',
4
- [null as any]: 'https://api.inngage.com.br/v1',
5
- [true as any]: 'https://apid.inngage.com.br/v1',
6
- }
7
-
8
- const requestConfigFactory = (method, request) => {
9
-
10
- let header: any = {
11
- Accept: 'application/json',
12
- 'Content-Type': 'application/json',
13
- }
14
- try {
15
- if (request?.registerSubscriberRequest?.authKey) {
16
- header = {
17
- ...header,
18
- Authorization: request.registerSubscriberRequest.authKey
19
- }
20
- }
21
- } catch (e) {
22
- console.error(e)
23
- }
24
- let objToSend = {
25
- method,
26
- body: JSON.stringify(request),
27
- headers: header
28
- }
29
-
30
- return objToSend
31
- }
32
-
33
- export const fetchClient = async (
34
- method: string,
35
- requestBody: any,
36
- path: string,
37
- isDev = false
38
- ): Promise<Response> => {
39
- try {
40
- const url: URL = new URL(`${baseUrlHook[isDev as any]}${path}`);
41
- const request: RequestInit = requestConfigFactory(method, requestBody);
42
- const response: Response = await fetch(url, request);
43
-
44
- if (!response.ok) {
45
- throw new Error(`Network response was not ok (${response.status})`);
46
- }
47
-
48
- return response;
49
- } catch (error: any) {
50
- console.error('Fetch Error:', error.message);
51
- throw error;
52
- }
53
- };
@@ -1,159 +0,0 @@
1
- import * as React from "react";
2
- import {
3
- StyleSheet,
4
- Image,
5
- View,
6
- Text,
7
- TouchableOpacity,
8
- ImageBackground,
9
- Dimensions,
10
- } from "react-native";
11
-
12
- import AsyncStorage from "@react-native-async-storage/async-storage";
13
- import Carousel from 'react-native-snap-carousel';
14
-
15
- import { buildStyles } from "./styles";
16
- import { Modal } from "../components/modal";
17
- import { InngageProperties } from "../models/inngage_properties";
18
-
19
- interface InAppData {
20
- inapp_message: boolean
21
- title: string
22
- body: string
23
- title_font_color: string
24
- body_font_color: string
25
- background_color: string
26
- btn_left_txt_color: string
27
- btn_left_bg_color: string
28
- btn_right_txt_color: string
29
- btn_right_bg_color: string
30
- background_image: string
31
- btn_left_txt: string
32
- btn_left_action_type: string
33
- btn_left_action_link: string
34
- btn_right_txt: string
35
- btn_right_action_type: string
36
- btn_right_action_link: string
37
- rich_content: string
38
- inpression: string
39
- bg_img_action_type: string
40
- bg_img_action_link: string
41
- dot_color: string
42
- }
43
-
44
- interface InAppRichContent {
45
- carousel: boolean
46
- img1: string
47
- img2: string
48
- img3: string
49
- img4: string
50
- img5: string
51
- }
52
-
53
- interface InAppProps {
54
- onDismiss: () => void;
55
- }
56
-
57
- export function InApp({ onDismiss }: InAppProps): JSX.Element {
58
- const { width: screenWidth } = Dimensions.get('window');
59
-
60
- const sliderWidth = screenWidth;
61
- const itemWidth = screenWidth * 0.9;
62
-
63
- const [data, setData] = React.useState<InAppData>();
64
- const [richContent, setRichContent] = React.useState<InAppRichContent>();
65
- const [visible, setVisible] = React.useState(false);
66
-
67
- React.useEffect(() => {
68
- const fetchAdditionalData = async () => {
69
- try {
70
- console.log('in app message')
71
- const data = await AsyncStorage.getItem('inapp');
72
- if (data) {
73
- const parsedData = JSON.parse(data);
74
- const richContentData = parsedData.rich_content;
75
-
76
- setVisible(true);
77
- setData(parsedData);
78
- setRichContent(richContentData);
79
- }
80
- } catch (error) {
81
- console.error('Error retrieving additionalData from AsyncStorage:', error);
82
- }
83
- };
84
-
85
- fetchAdditionalData();
86
- }, []);
87
-
88
- const styles = buildStyles(data, screenWidth * 0.9);
89
-
90
- const handleDismissInApp = async () => {
91
- await AsyncStorage.removeItem('inapp');
92
- setVisible(false);
93
- onDismiss();
94
- }
95
-
96
- const imageUrls: string[] = [
97
- richContent?.img1 ?? '',
98
- richContent?.img2 ?? '',
99
- richContent?.img3 ?? '',
100
- richContent?.img4 ?? '',
101
- richContent?.img5 ?? ''
102
- ];
103
-
104
- const stylesCarousel = StyleSheet.create({
105
- itemContainer: {
106
- justifyContent: 'center',
107
- height: 250
108
- },
109
- itemImg: {
110
- height: 250,
111
- },
112
- });
113
-
114
- const _renderItem = ({ item, index }) => {
115
- return (
116
- <View style={stylesCarousel.itemContainer}>
117
- <Image style={[stylesCarousel.itemImg]} source={{ uri: item }} />
118
- </View>
119
- )
120
- }
121
-
122
- if (InngageProperties.getDebugMode() && data != null) {
123
- console.log('INNGAGE - Data In App:', data)
124
- console.log('INNGAGE - Data Rich Content:', richContent)
125
- }
126
-
127
- return (
128
- <Modal
129
- renderToHardwareTextureAndroid={true}
130
- transparent={true}
131
- visible={visible}>
132
- <ImageBackground style={styles.content} source={{ uri: data?.background_image }}>
133
- {richContent?.carousel ? <Carousel
134
- layout={"default"}
135
- data={imageUrls}
136
- sliderWidth={sliderWidth}
137
- itemWidth={itemWidth}
138
- renderItem={_renderItem} /> : null}
139
- <TouchableOpacity style={styles.closeButton} onPress={handleDismissInApp}>
140
- <Text>X</Text>
141
- </TouchableOpacity>
142
- <View style={styles.messageData}>
143
- <Text style={styles.title}>{data?.title}</Text>
144
- <Text style={styles.body}>{data?.body}</Text>
145
- </View>
146
- <View style={styles.footer}>
147
- {data?.btn_left_txt != null ? <TouchableOpacity
148
- style={styles.buttonLeft}>
149
- <Text style={styles.textButton}>{data?.btn_left_txt}</Text>
150
- </TouchableOpacity> : null}
151
- {data?.btn_right_txt != null ? <TouchableOpacity
152
- style={styles.buttonRight}>
153
- <Text style={styles.textButton}>{data?.btn_right_txt}</Text>
154
- </TouchableOpacity> : null}
155
- </View>
156
- </ImageBackground>
157
- </Modal>
158
- )
159
- }