@inngageregistry/inngage-react 3.3.1-alpha.1 → 4.0.0-alpha.1
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.
- package/package.json +1 -1
- package/src/Inngage.ts +131 -134
- package/src/api/api.ts +28 -0
- package/src/api/handler.ts +53 -0
- package/src/components/in_app.tsx +117 -0
- package/src/firebase/notifications_listener.ts +105 -0
- package/src/index.ts +2 -2
- package/src/models/requests.ts +42 -0
- package/src/services/api_service.ts +30 -0
- package/src/components/Inapp.tsx +0 -324
- package/src/notificationsListener.ts +0 -189
- package/src/services/handler.ts +0 -42
- package/src/services/inngage.ts +0 -23
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inngageregistry/inngage-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-alpha.01",
|
|
4
4
|
"description": "Inngage Plugin for React Native applications for marketing campaign optimization using Push Notification.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.d.ts",
|
package/src/Inngage.ts
CHANGED
|
@@ -3,62 +3,62 @@ import DeviceInfo from "react-native-device-info";
|
|
|
3
3
|
import * as RNLocalize from "react-native-localize";
|
|
4
4
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
5
5
|
|
|
6
|
-
import { addUserDataRequest, eventRequest, formatDate
|
|
7
|
-
import
|
|
8
|
-
import { subscriptionApi, eventsApi, addUserDataApi } from "./services/inngage";
|
|
6
|
+
import { addUserDataRequest, eventRequest, formatDate } from "./utils";
|
|
7
|
+
import { InngageNotificationMessage } from "./firebase/notifications_listener";
|
|
9
8
|
import { InngageProperties } from './models/inngage_properties';
|
|
10
9
|
|
|
11
10
|
import RNPermissions, { NotificationOption, RESULTS } from 'react-native-permissions';
|
|
12
11
|
|
|
12
|
+
import ApiService from './services/api_service';
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
SUBSCRIBE_REQUEST,
|
|
16
|
+
EVENT_REQUEST,
|
|
17
|
+
USER_DATA_REQUEST,
|
|
18
|
+
} from './models/requests';
|
|
19
|
+
|
|
20
|
+
const API_LEVEL_33 = 33;
|
|
21
|
+
|
|
13
22
|
// --- Get Firebase Access ------/
|
|
14
|
-
const getFirebaseAccess = async ()
|
|
15
|
-
|
|
16
|
-
return await handleNotificationsPermission();
|
|
17
|
-
} catch (error) {
|
|
18
|
-
console.log('Erro no getFirebaseAccess: ', error);
|
|
19
|
-
throw error;
|
|
20
|
-
}
|
|
23
|
+
const getFirebaseAccess = async () => {
|
|
24
|
+
return await handleNotificationsPermission();
|
|
21
25
|
};
|
|
22
26
|
|
|
23
27
|
const handleNotificationsPermission = async () => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
console.error(error);
|
|
37
|
-
throw error;
|
|
28
|
+
const options: NotificationOption[] = ['alert', 'badge', 'sound'];
|
|
29
|
+
const apiLevel = await DeviceInfo.getApiLevel();
|
|
30
|
+
|
|
31
|
+
const permissionGranted =
|
|
32
|
+
apiLevel >= API_LEVEL_33
|
|
33
|
+
? (await RNPermissions.requestNotifications(options)).status === RESULTS.GRANTED
|
|
34
|
+
: (await firebase.messaging().requestPermission()) ===
|
|
35
|
+
firebase.messaging.AuthorizationStatus.AUTHORIZED ||
|
|
36
|
+
firebase.messaging.AuthorizationStatus.PROVISIONAL;
|
|
37
|
+
|
|
38
|
+
if (permissionGranted) {
|
|
39
|
+
return await getFirebaseToken();
|
|
38
40
|
}
|
|
41
|
+
|
|
42
|
+
throw new Error('Notification permission not granted');
|
|
39
43
|
};
|
|
40
44
|
|
|
41
|
-
const getFirebaseToken = async ()
|
|
42
|
-
|
|
43
|
-
let fcmToken = await AsyncStorage.getItem('fcmToken');
|
|
45
|
+
const getFirebaseToken = async () => {
|
|
46
|
+
let fcmToken = await AsyncStorage.getItem('fcmToken');
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
if (!fcmToken) {
|
|
49
|
+
if (!firebase.messaging().isDeviceRegisteredForRemoteMessages) {
|
|
50
|
+
await firebase.messaging().registerDeviceForRemoteMessages?.();
|
|
51
|
+
}
|
|
49
52
|
|
|
50
|
-
|
|
53
|
+
const newFcmToken = await firebase.messaging().getToken?.();
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
55
|
+
if (newFcmToken) {
|
|
56
|
+
await AsyncStorage.setItem('fcmToken', newFcmToken);
|
|
57
|
+
return newFcmToken;
|
|
56
58
|
}
|
|
57
|
-
return fcmToken || null;
|
|
58
|
-
} catch (error) {
|
|
59
|
-
console.error(error);
|
|
60
|
-
throw error;
|
|
61
59
|
}
|
|
60
|
+
|
|
61
|
+
return fcmToken || null;
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
interface SubscriptionProps {
|
|
@@ -83,127 +83,124 @@ interface SendEventProps {
|
|
|
83
83
|
eventValues?: any
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
class Inngage {
|
|
87
|
+
private static instance: Inngage;
|
|
88
|
+
private apiService: ApiService;
|
|
89
|
+
|
|
90
|
+
constructor() {
|
|
91
|
+
this.apiService = new ApiService();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static getInstance(): Inngage {
|
|
95
|
+
if (!Inngage.instance) {
|
|
96
|
+
Inngage.instance = new Inngage();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return Inngage.instance;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
static async notificationListener(firebaseListenCallback?: any) {
|
|
89
103
|
try {
|
|
90
|
-
|
|
104
|
+
InngageNotificationMessage(firebaseListenCallback)
|
|
91
105
|
} catch (e) {
|
|
92
|
-
console.
|
|
93
|
-
return { subscribed: false };
|
|
106
|
+
console.log(e)
|
|
94
107
|
}
|
|
95
|
-
}
|
|
108
|
+
}
|
|
96
109
|
|
|
97
|
-
|
|
110
|
+
static async subscribe({
|
|
98
111
|
appToken,
|
|
99
|
-
dev,
|
|
100
112
|
friendlyIdentifier,
|
|
101
113
|
customFields,
|
|
102
|
-
customData,
|
|
103
114
|
phoneNumber,
|
|
104
115
|
email,
|
|
105
|
-
}: SubscriptionProps)
|
|
116
|
+
}: SubscriptionProps) {
|
|
117
|
+
const inngage = Inngage.getInstance();
|
|
118
|
+
|
|
106
119
|
InngageProperties.appToken = appToken;
|
|
107
120
|
InngageProperties.identifier = friendlyIdentifier!;
|
|
108
121
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
email: email,
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
const request = subscriptionRequestAdapter(rawRequest, customData, customFields)
|
|
145
|
-
const subscribe = await subscriptionApi(request, dev);
|
|
146
|
-
console.log(await subscribe.json())
|
|
147
|
-
return subscribe;
|
|
148
|
-
} catch (e) {
|
|
149
|
-
console.error(e);
|
|
150
|
-
return { subscribed: false };
|
|
122
|
+
const respToken = await getFirebaseAccess();
|
|
123
|
+
|
|
124
|
+
const { countryCode: osLocale, languageCode: osLanguage } = RNLocalize.getLocales()[0] || {};
|
|
125
|
+
const deviceManufacturer = await DeviceInfo.getManufacturer();
|
|
126
|
+
const installTime = await DeviceInfo.getFirstInstallTime();
|
|
127
|
+
const lastUpdateTime = await DeviceInfo.getLastUpdateTime();
|
|
128
|
+
const uuid = await DeviceInfo.getUniqueId();
|
|
129
|
+
const appInstalledIn = formatDate(installTime);
|
|
130
|
+
const appUpdatedIn = formatDate(lastUpdateTime);
|
|
131
|
+
|
|
132
|
+
const subscription = {
|
|
133
|
+
...SUBSCRIBE_REQUEST,
|
|
134
|
+
registerSubscriberRequest: {
|
|
135
|
+
app_token: appToken,
|
|
136
|
+
identifier: friendlyIdentifier,
|
|
137
|
+
registration: respToken,
|
|
138
|
+
platform: DeviceInfo.getSystemName(),
|
|
139
|
+
sdk: DeviceInfo.getBuildNumber(),
|
|
140
|
+
deviceModel: DeviceInfo.getModel(),
|
|
141
|
+
deviceManufacturer,
|
|
142
|
+
osLocale,
|
|
143
|
+
osLanguage,
|
|
144
|
+
os_version: DeviceInfo.getReadableVersion(),
|
|
145
|
+
app_version: DeviceInfo.getBuildNumber(),
|
|
146
|
+
appInstalledIn,
|
|
147
|
+
appUpdatedIn,
|
|
148
|
+
uuid,
|
|
149
|
+
phone_Number: phoneNumber,
|
|
150
|
+
email: email,
|
|
151
|
+
customFields: customFields,
|
|
152
|
+
}
|
|
151
153
|
}
|
|
152
|
-
},
|
|
153
154
|
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
return inngage.apiService.subscribe(subscription);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
static async sendEvent({
|
|
156
159
|
eventName,
|
|
157
|
-
identifier,
|
|
158
|
-
registration,
|
|
159
160
|
conversionEvent,
|
|
160
161
|
conversionValue,
|
|
161
162
|
conversionNotId,
|
|
162
163
|
eventValues,
|
|
163
|
-
}: SendEventProps)
|
|
164
|
+
}: SendEventProps) {
|
|
165
|
+
const inngage = Inngage.getInstance();
|
|
166
|
+
|
|
167
|
+
const registration = await getFirebaseAccess();
|
|
164
168
|
|
|
165
|
-
const
|
|
169
|
+
const request = eventRequest({
|
|
170
|
+
...EVENT_REQUEST,
|
|
166
171
|
newEventRequest: {
|
|
167
|
-
|
|
168
|
-
identifier: identifier,
|
|
169
|
-
registration
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
};
|
|
172
|
+
appToken: InngageProperties.appToken,
|
|
173
|
+
identifier: InngageProperties.identifier,
|
|
174
|
+
registration,
|
|
175
|
+
eventName,
|
|
176
|
+
conversionEvent: !!conversionEvent,
|
|
177
|
+
conversionValue,
|
|
178
|
+
conversionNotId,
|
|
179
|
+
eventValues,
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
return inngage.apiService.sendEvent(request);
|
|
184
|
+
}
|
|
177
185
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return await eventsApi(request);
|
|
181
|
-
} catch (e) {
|
|
182
|
-
console.error(e)
|
|
183
|
-
return { subscribed: false };
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
+
static async addUserData(customFields: any): Promise<any> {
|
|
187
|
+
const inngage = Inngage.getInstance();
|
|
186
188
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
+
const request = addUserDataRequest({
|
|
190
|
+
...USER_DATA_REQUEST,
|
|
189
191
|
fieldsRequest: {
|
|
190
|
-
|
|
192
|
+
appToken: InngageProperties.appToken,
|
|
191
193
|
identifier: InngageProperties.identifier,
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
};
|
|
194
|
+
customField: customFields,
|
|
195
|
+
},
|
|
196
|
+
});
|
|
195
197
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
return await addUserDataApi(request);
|
|
199
|
-
} catch (e) {
|
|
200
|
-
console.error(e);
|
|
201
|
-
}
|
|
202
|
-
},
|
|
198
|
+
return inngage.apiService.addUserData(request);
|
|
199
|
+
}
|
|
203
200
|
|
|
204
|
-
setDebugMode(value: boolean) {
|
|
205
|
-
InngageProperties.debugMode = value
|
|
201
|
+
static setDebugMode(value: boolean) {
|
|
202
|
+
InngageProperties.debugMode = value;
|
|
206
203
|
}
|
|
207
204
|
}
|
|
208
205
|
|
|
209
|
-
export default Inngage;
|
|
206
|
+
export default Inngage;
|
package/src/api/api.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { fetchClient } from './handler'
|
|
2
|
+
|
|
3
|
+
const apiEndpoints = {
|
|
4
|
+
subscription: '/subscription/',
|
|
5
|
+
notification: '/notification/',
|
|
6
|
+
events: '/events/newEvent/',
|
|
7
|
+
addUserData: '/subscription/addCustomField',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const makeApiCall = (method: string, request: any, endpoint: string) => {
|
|
11
|
+
return fetchClient(method, request, endpoint);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const subscriptionApi = (request: any) => {
|
|
15
|
+
return makeApiCall('POST', request, apiEndpoints.subscription);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const notificationApi = (request: any) => {
|
|
19
|
+
return makeApiCall('POST', request, apiEndpoints.notification);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const eventsApi = (request: any) => {
|
|
23
|
+
return makeApiCall('POST', request, apiEndpoints.events);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const addUserDataApi = (request: any) => {
|
|
27
|
+
return makeApiCall('POST', request, apiEndpoints.addUserData);
|
|
28
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Modal,
|
|
4
|
+
View,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
Text,
|
|
7
|
+
TouchableOpacity,
|
|
8
|
+
ImageBackground,
|
|
9
|
+
Platform,
|
|
10
|
+
PlatformColor,
|
|
11
|
+
} from "react-native";
|
|
12
|
+
|
|
13
|
+
export function InAppContainer(data: any): JSX.Element {
|
|
14
|
+
const styles = buildStyles(data)
|
|
15
|
+
return (
|
|
16
|
+
<Modal
|
|
17
|
+
renderToHardwareTextureAndroid={true}
|
|
18
|
+
transparent={true}
|
|
19
|
+
visible={true}>
|
|
20
|
+
<ImageBackground style={styles.content} source={{ uri: "" }}>
|
|
21
|
+
<View style={styles.messageData}>
|
|
22
|
+
<Text style={styles.title}>data.title</Text>
|
|
23
|
+
<Text style={styles.body}>Corpo</Text>
|
|
24
|
+
</View>
|
|
25
|
+
<View style={styles.footer}>
|
|
26
|
+
<TouchableOpacity
|
|
27
|
+
style={styles.button}>
|
|
28
|
+
<Text style={styles.textButton}>Teste</Text>
|
|
29
|
+
</TouchableOpacity>
|
|
30
|
+
<TouchableOpacity
|
|
31
|
+
style={styles.button}>
|
|
32
|
+
<Text style={styles.textButton}>Teste</Text>
|
|
33
|
+
</TouchableOpacity>
|
|
34
|
+
</View>
|
|
35
|
+
</ImageBackground>
|
|
36
|
+
</Modal>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const buildStyles = ({ data }) => StyleSheet.create({
|
|
41
|
+
content: Platform.select({
|
|
42
|
+
android: {
|
|
43
|
+
backgroundColor: PlatformColor("?attr/colorBackgroundFloating"),
|
|
44
|
+
flexDirection: "column",
|
|
45
|
+
borderRadius: 3,
|
|
46
|
+
padding: 16,
|
|
47
|
+
margin: 16,
|
|
48
|
+
overflow: "hidden",
|
|
49
|
+
elevation: 10,
|
|
50
|
+
minWidth: 300,
|
|
51
|
+
alignItems: "center"
|
|
52
|
+
},
|
|
53
|
+
default: {}
|
|
54
|
+
}),
|
|
55
|
+
messageData: Platform.select({
|
|
56
|
+
android: {
|
|
57
|
+
marginTop: 12
|
|
58
|
+
},
|
|
59
|
+
default: {}
|
|
60
|
+
}),
|
|
61
|
+
footer: {
|
|
62
|
+
flexDirection: "row",
|
|
63
|
+
...Platform.select({
|
|
64
|
+
android: {
|
|
65
|
+
alignItems: "center",
|
|
66
|
+
justifyContent: "flex-end",
|
|
67
|
+
marginTop: 4,
|
|
68
|
+
},
|
|
69
|
+
default: {},
|
|
70
|
+
}),
|
|
71
|
+
},
|
|
72
|
+
title: Platform.select({
|
|
73
|
+
android: {
|
|
74
|
+
color: PlatformColor(
|
|
75
|
+
`@android:color/${"primary_text_light"}`
|
|
76
|
+
),
|
|
77
|
+
fontWeight: "500",
|
|
78
|
+
fontSize: 18,
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
default: {},
|
|
82
|
+
}),
|
|
83
|
+
body: Platform.select({
|
|
84
|
+
android: {
|
|
85
|
+
color: PlatformColor(
|
|
86
|
+
`@android:color/${"secondary_text_light"}`
|
|
87
|
+
),
|
|
88
|
+
fontSize: 16,
|
|
89
|
+
marginTop: 10,
|
|
90
|
+
marginBottom: 10,
|
|
91
|
+
},
|
|
92
|
+
default: {},
|
|
93
|
+
}),
|
|
94
|
+
button: Platform.select({
|
|
95
|
+
android: {
|
|
96
|
+
margin: 2,
|
|
97
|
+
flex: 1,
|
|
98
|
+
backgroundColor: "red",
|
|
99
|
+
justifyContent: "center",
|
|
100
|
+
alignItems: "center",
|
|
101
|
+
},
|
|
102
|
+
default: {},
|
|
103
|
+
}),
|
|
104
|
+
textButton: Platform.select({
|
|
105
|
+
android: {
|
|
106
|
+
color: PlatformColor(
|
|
107
|
+
`@android:color/${"secondary_text_light"}`
|
|
108
|
+
),
|
|
109
|
+
textAlign: "center",
|
|
110
|
+
backgroundColor: "transparent",
|
|
111
|
+
padding: 8,
|
|
112
|
+
fontSize: 14,
|
|
113
|
+
textTransform: "uppercase",
|
|
114
|
+
},
|
|
115
|
+
default: {},
|
|
116
|
+
}),
|
|
117
|
+
})
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
4
|
+
|
|
5
|
+
import messaging from '@react-native-firebase/messaging';
|
|
6
|
+
import PushNotification, { Importance } from 'react-native-push-notification'
|
|
7
|
+
|
|
8
|
+
import { InngageProperties } from '../models/inngage_properties';
|
|
9
|
+
import * as ApiService from '../services/api_service'
|
|
10
|
+
|
|
11
|
+
export const InngageNotificationMessage = (firebaseListenCallback?: any) => {
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
PushNotification.configure({
|
|
14
|
+
onNotification: function (data: any) {
|
|
15
|
+
if (data.foreground) {
|
|
16
|
+
handleNotification(data)
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
popInitialNotification: true,
|
|
20
|
+
requestPermissions: true
|
|
21
|
+
})
|
|
22
|
+
PushNotification.createChannel({
|
|
23
|
+
channelId: 'channel_id',
|
|
24
|
+
channelName: 'default',
|
|
25
|
+
importance: Importance.HIGH,
|
|
26
|
+
playSound: true,
|
|
27
|
+
soundName: 'default',
|
|
28
|
+
vibrate: true
|
|
29
|
+
}, (created: any) => {
|
|
30
|
+
if (created) {
|
|
31
|
+
console.log('Channel created');
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
})
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const handleMessage = async (remoteMessage: any) => {
|
|
37
|
+
if (InngageProperties.getDebugMode())
|
|
38
|
+
console.log('Remote message received in foreground: ', remoteMessage);
|
|
39
|
+
|
|
40
|
+
if (firebaseListenCallback != null && remoteMessage != null)
|
|
41
|
+
firebaseListenCallback(remoteMessage.data)
|
|
42
|
+
|
|
43
|
+
PushNotification.localNotification({
|
|
44
|
+
autoCancel: true,
|
|
45
|
+
bigPictureUrl: remoteMessage.notification?.android?.imageUrl,
|
|
46
|
+
largeIconUrl: remoteMessage.notification?.android?.imageUrl,
|
|
47
|
+
title: remoteMessage.data?.title,
|
|
48
|
+
message: remoteMessage.data?.body,
|
|
49
|
+
vibration: 300,
|
|
50
|
+
channelId: "channel_id",
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
return messaging().onMessage(handleMessage);
|
|
55
|
+
}, []);
|
|
56
|
+
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
const backgroundHandler = async (remoteMessage: any) => {
|
|
59
|
+
if (InngageProperties.getDebugMode())
|
|
60
|
+
console.log('Remote message received in background: ', remoteMessage);
|
|
61
|
+
|
|
62
|
+
if (remoteMessage != null)
|
|
63
|
+
firebaseListenCallback(remoteMessage.data)
|
|
64
|
+
|
|
65
|
+
messaging().onNotificationOpenedApp(remoteMessage => {
|
|
66
|
+
handleNotification(remoteMessage)
|
|
67
|
+
})
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return messaging().setBackgroundMessageHandler(backgroundHandler);
|
|
71
|
+
}, []);
|
|
72
|
+
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
messaging().getInitialNotification().then(async (value) => {
|
|
75
|
+
if (value !== null)
|
|
76
|
+
handleUniqueRemoteMessage(value);
|
|
77
|
+
});
|
|
78
|
+
}, [])
|
|
79
|
+
|
|
80
|
+
const handleUniqueRemoteMessage = async (
|
|
81
|
+
remoteMessage: { messageId?: string }) => {
|
|
82
|
+
try {
|
|
83
|
+
const lastRemoteMessageId = await AsyncStorage.getItem('LAST_REMOTE_MESSAGE_ID');
|
|
84
|
+
const newRemoteMessageId = remoteMessage?.messageId;
|
|
85
|
+
|
|
86
|
+
if (newRemoteMessageId && lastRemoteMessageId !== newRemoteMessageId) {
|
|
87
|
+
await AsyncStorage.setItem('LAST_REMOTE_MESSAGE_ID', newRemoteMessageId);
|
|
88
|
+
handleNotification(remoteMessage)
|
|
89
|
+
}
|
|
90
|
+
} catch (e) {
|
|
91
|
+
console.log(e);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
async function handleNotification(remoteMessage) {
|
|
96
|
+
const notId = remoteMessage.data?.notId;
|
|
97
|
+
const request = {
|
|
98
|
+
notificationRequest: {
|
|
99
|
+
id: notId,
|
|
100
|
+
app_token: InngageProperties.appToken,
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
await ApiService.sendNotification(request);
|
|
104
|
+
}
|
|
105
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InAppContainer } from './components/in_app';
|
|
2
2
|
import Inngage from './Inngage';
|
|
3
3
|
|
|
4
4
|
//-------------- In-APP Component -------------//
|
|
5
|
-
export {
|
|
5
|
+
export { InAppContainer };
|
|
6
6
|
|
|
7
7
|
//-------------- Inngage Wrapper --------------//
|
|
8
8
|
export default Inngage;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export const SUBSCRIBE_REQUEST = {
|
|
2
|
+
registerSubscriberRequest: {
|
|
3
|
+
appToken: '',
|
|
4
|
+
identifier: '',
|
|
5
|
+
registration: '',
|
|
6
|
+
platform: '',
|
|
7
|
+
sdk: '',
|
|
8
|
+
deviceModel: '',
|
|
9
|
+
deviceManufacturer: '',
|
|
10
|
+
osLocale: '',
|
|
11
|
+
osLanguage: '',
|
|
12
|
+
osVersion: '',
|
|
13
|
+
appVersion: '',
|
|
14
|
+
appInstalledIn: '',
|
|
15
|
+
appUpdatedIn: '',
|
|
16
|
+
uuid: '',
|
|
17
|
+
phoneNumber: '',
|
|
18
|
+
email: '',
|
|
19
|
+
customFields: {},
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const EVENT_REQUEST = {
|
|
24
|
+
newEventRequest: {
|
|
25
|
+
appToken: '',
|
|
26
|
+
identifier: '',
|
|
27
|
+
registration: '',
|
|
28
|
+
eventName: '',
|
|
29
|
+
conversionEvent: false,
|
|
30
|
+
conversionValue: 0,
|
|
31
|
+
conversionNotId: '',
|
|
32
|
+
eventValues: {},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const USER_DATA_REQUEST = {
|
|
37
|
+
fieldsRequest: {
|
|
38
|
+
appToken: '',
|
|
39
|
+
identifier: '',
|
|
40
|
+
customField: {},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { InngageProperties } from '../models/inngage_properties';
|
|
2
|
+
import { subscriptionApi, notificationApi, eventsApi, addUserDataApi } from '../api/api';
|
|
3
|
+
|
|
4
|
+
class ApiService {
|
|
5
|
+
async subscribe(request: any) {
|
|
6
|
+
if (InngageProperties.getDebugMode())
|
|
7
|
+
console.log('INNGAGE PAYLOAD SUBSCRIPTION: ', request)
|
|
8
|
+
return subscriptionApi(request);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async sendEvent(request: any, dev = false) {
|
|
12
|
+
if (InngageProperties.getDebugMode())
|
|
13
|
+
console.log('INNGAGE PAYLOAD EVENT: ', request)
|
|
14
|
+
return eventsApi(request);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async addUserData(request: any, dev = false) {
|
|
18
|
+
if (InngageProperties.getDebugMode())
|
|
19
|
+
console.log('INNGAGE PAYLOAD ADDUSERDATA: ', request)
|
|
20
|
+
return addUserDataApi(request);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function sendNotification(request: any, dev = false) {
|
|
25
|
+
if (InngageProperties.getDebugMode())
|
|
26
|
+
console.log('INNGAGE PAYLOAD NOTIFICATION: ', request)
|
|
27
|
+
return notificationApi(request);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default ApiService;
|
package/src/components/Inapp.tsx
DELETED
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
Modal,
|
|
4
|
-
View,
|
|
5
|
-
Text,
|
|
6
|
-
TouchableHighlight,
|
|
7
|
-
TouchableOpacity,
|
|
8
|
-
Image,
|
|
9
|
-
ScrollView,
|
|
10
|
-
ImageBackground,
|
|
11
|
-
Linking,
|
|
12
|
-
Dimensions,
|
|
13
|
-
} from "react-native";
|
|
14
|
-
import DeviceInfo from "react-native-device-info";
|
|
15
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
16
|
-
import Carousel, { Pagination } from 'react-native-snap-carousel';
|
|
17
|
-
|
|
18
|
-
import { showAlertLink, isEmpty } from "../utils";
|
|
19
|
-
import { linkInApp } from "../notificationsListener";
|
|
20
|
-
import { styleInapp, styleItem } from './styles';
|
|
21
|
-
|
|
22
|
-
const SLIDER_WIDTH = Dimensions.get('window').width;
|
|
23
|
-
const SLIDER_HEIGHT = Dimensions.get('window').height;
|
|
24
|
-
const ITEM_WIDTH = Math.round(SLIDER_WIDTH * 0.8);
|
|
25
|
-
const ITEM_HEIGHT = Math.round(SLIDER_HEIGHT * 0.8);
|
|
26
|
-
|
|
27
|
-
export interface InappProps {
|
|
28
|
-
mediaStyle?: any;
|
|
29
|
-
titleStyle?: any;
|
|
30
|
-
bodyStyle?: any;
|
|
31
|
-
buttonLeftStyle?: any;
|
|
32
|
-
buttonRightStyle?: any;
|
|
33
|
-
buttonTitleLeftStyle?: any;
|
|
34
|
-
buttonTitleRightStyle?: any;
|
|
35
|
-
styleContainer?: any;
|
|
36
|
-
onClose?: 'clear';
|
|
37
|
-
}
|
|
38
|
-
export const Inapp = (props: InappProps) => {
|
|
39
|
-
const [data, setData] = useState<any>([])
|
|
40
|
-
const [indIm, setIndImg] = useState(0)
|
|
41
|
-
const [visible, setVisible] = useState(true)
|
|
42
|
-
const [bgImage, setbgImage] = useState<any>(undefined) // TODO, need a placeholder
|
|
43
|
-
|
|
44
|
-
const CarouselRef = useRef<Carousel<any>>(null);
|
|
45
|
-
const ScrollRef1 = useRef<ScrollView>(null);
|
|
46
|
-
const ScrollRef2 = useRef<ScrollView>(null);
|
|
47
|
-
const ScrollRef3 = useRef<ScrollView>(null);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
interface _renderItemProps {
|
|
51
|
-
item: any;
|
|
52
|
-
index: number;
|
|
53
|
-
}
|
|
54
|
-
const _renderItem = ({ item, index }: _renderItemProps) => {
|
|
55
|
-
let msg = JSON.parse(item.data.additional_data)
|
|
56
|
-
let arrayImgs: any = []
|
|
57
|
-
let indImg = 0
|
|
58
|
-
|
|
59
|
-
const checkBG = () => {
|
|
60
|
-
if (msg.background_img != '') {
|
|
61
|
-
return null
|
|
62
|
-
} else {
|
|
63
|
-
return msg.background_color
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const itemStyles = styleItem({ msg, checkBG })
|
|
68
|
-
|
|
69
|
-
const chooseRef = () => {
|
|
70
|
-
if (index == 0) {
|
|
71
|
-
return ScrollRef1
|
|
72
|
-
}
|
|
73
|
-
if (index == 1) {
|
|
74
|
-
return ScrollRef2
|
|
75
|
-
}
|
|
76
|
-
if (index == 2) {
|
|
77
|
-
return ScrollRef3
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const pagination = ref => {
|
|
83
|
-
return (
|
|
84
|
-
<Pagination
|
|
85
|
-
dotsLength={arrayImgs.length}
|
|
86
|
-
activeDotIndex={indIm}
|
|
87
|
-
containerStyle={{ height: 2, padding: 0, margin: 0 }}
|
|
88
|
-
renderDots={(activeIndex, total, context) => {
|
|
89
|
-
let dots: any = []
|
|
90
|
-
var size = 0
|
|
91
|
-
for (let i = 0; i < total; i++) {
|
|
92
|
-
if (activeIndex == i) {
|
|
93
|
-
size = 13
|
|
94
|
-
} else {
|
|
95
|
-
size = 8
|
|
96
|
-
}
|
|
97
|
-
dots.push(
|
|
98
|
-
<TouchableOpacity
|
|
99
|
-
onPress={() => {
|
|
100
|
-
ref.current.scrollTo({ x: i * 220, y: 0, animated: true })
|
|
101
|
-
if (i * 220 === 0) {
|
|
102
|
-
setIndImg(0)
|
|
103
|
-
} else if (i * 220 === 220) {
|
|
104
|
-
setIndImg(1)
|
|
105
|
-
} else if (i * 220 === 440) {
|
|
106
|
-
setIndImg(2)
|
|
107
|
-
}
|
|
108
|
-
}}
|
|
109
|
-
key={i.toString()}
|
|
110
|
-
style={[itemStyles.dot, { width: size, height: size }]}
|
|
111
|
-
/>
|
|
112
|
-
)
|
|
113
|
-
}
|
|
114
|
-
return (
|
|
115
|
-
dots
|
|
116
|
-
)
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/>
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const handleButton = (title: string, body: string, url: string, type: string) => {
|
|
124
|
-
if (type === '' || url === '') {
|
|
125
|
-
return
|
|
126
|
-
}
|
|
127
|
-
console.log(title, body, url, type)
|
|
128
|
-
const openLinkByType = (type, url) => (type === 'deep' ? Linking.openURL(url) : linkInApp(url))
|
|
129
|
-
|
|
130
|
-
return Linking.canOpenURL(url).then((supported) => {
|
|
131
|
-
if (supported) {
|
|
132
|
-
showAlertLink(
|
|
133
|
-
title,
|
|
134
|
-
body,
|
|
135
|
-
`${DeviceInfo.getApplicationName()}`,
|
|
136
|
-
`Acessar ${url} ?`,
|
|
137
|
-
).then(() => { supported && openLinkByType(type, url) })
|
|
138
|
-
}
|
|
139
|
-
}).catch(console.error)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const imgCarosel = () => {
|
|
143
|
-
if (msg.rich_content.carousel == true) {
|
|
144
|
-
if (msg.rich_content.img1 != '') {
|
|
145
|
-
arrayImgs.push({ url: msg.rich_content.img1 })
|
|
146
|
-
}
|
|
147
|
-
if (msg.rich_content.img2 != '') {
|
|
148
|
-
arrayImgs.push({ url: msg.rich_content.img2 })
|
|
149
|
-
}
|
|
150
|
-
if (msg.rich_content.img3 != '') {
|
|
151
|
-
arrayImgs.push({ url: msg.rich_content.img3 })
|
|
152
|
-
}
|
|
153
|
-
let arrayElements = arrayImgs.map((item, index) => (
|
|
154
|
-
<Image key={index.toString()} style={[props.mediaStyle, { width: 200, height: 200, marginRight: 10 }]} source={{ uri: item.url }} />
|
|
155
|
-
));
|
|
156
|
-
return arrayElements
|
|
157
|
-
} else if (arrayImgs.length <= 0) {
|
|
158
|
-
return (
|
|
159
|
-
<Image style={[props.mediaStyle, { width: 200, height: 200 }]} source={{ uri: item.data.picture }} />
|
|
160
|
-
)
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
return (
|
|
164
|
-
<Image style={[props.mediaStyle, { width: 200, height: 200 }]} source={{ uri: item.data.picture }} />
|
|
165
|
-
)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return (
|
|
169
|
-
<View style={[itemStyles.body]}>
|
|
170
|
-
<Text style={[itemStyles.title, props.titleStyle]}>{msg.title}</Text>
|
|
171
|
-
<ScrollView
|
|
172
|
-
ref={chooseRef()}
|
|
173
|
-
horizontal
|
|
174
|
-
snapToInterval={220}
|
|
175
|
-
decelerationRate="fast"
|
|
176
|
-
showsHorizontalScrollIndicator={false}
|
|
177
|
-
style={{ width: 200, height: 240 }}
|
|
178
|
-
contentContainerStyle={{ alignItems: 'center', justifyContent: 'center' }}
|
|
179
|
-
onMomentumScrollEnd={(e) => {
|
|
180
|
-
if (Math.round(e.nativeEvent.contentOffset.x) === 0
|
|
181
|
-
) {
|
|
182
|
-
indImg = 0
|
|
183
|
-
setIndImg(indImg)
|
|
184
|
-
}
|
|
185
|
-
if (Math.round(e.nativeEvent.contentOffset.x) === 220
|
|
186
|
-
) {
|
|
187
|
-
indImg = 1
|
|
188
|
-
setIndImg(indImg)
|
|
189
|
-
}
|
|
190
|
-
if (Math.round(e.nativeEvent.contentOffset.x) === 430
|
|
191
|
-
) {
|
|
192
|
-
indImg = 2
|
|
193
|
-
setIndImg(indImg)
|
|
194
|
-
}
|
|
195
|
-
}}
|
|
196
|
-
>
|
|
197
|
-
{imgCarosel()}
|
|
198
|
-
</ScrollView>
|
|
199
|
-
{
|
|
200
|
-
msg.rich_content.carousel == true ?
|
|
201
|
-
pagination(chooseRef()) : null
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
<Text style={[itemStyles.bodyText, props.bodyStyle]}>{msg.body}</Text>
|
|
205
|
-
<View style={{ flexDirection: "row", marginBottom: 0, justifyContent: 'center' }}>
|
|
206
|
-
<TouchableOpacity onPress={() => handleButton(msg.title, msg.body, msg.btn_left_action_link, msg.btn_left_action_type)} style={[itemStyles.btn_left, props.buttonLeftStyle]}>
|
|
207
|
-
<View>
|
|
208
|
-
<Text style={[itemStyles.btn_left_title, props.buttonTitleLeftStyle]}>{msg.btn_left_txt}</Text>
|
|
209
|
-
</View>
|
|
210
|
-
</TouchableOpacity>
|
|
211
|
-
<TouchableOpacity onPress={() => handleButton(msg.title, msg.body, msg.btn_right_action_link, msg.btn_right_action_type)} style={[itemStyles.btn_right, props.buttonRightStyle]}>
|
|
212
|
-
<View>
|
|
213
|
-
<Text style={[itemStyles.btn_right_title, props.buttonTitleRightStyle]}>{msg.btn_right_txt}</Text>
|
|
214
|
-
</View>
|
|
215
|
-
</TouchableOpacity>
|
|
216
|
-
</View>
|
|
217
|
-
</View>
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
useEffect(() => {
|
|
222
|
-
onLoad();
|
|
223
|
-
}, [])
|
|
224
|
-
|
|
225
|
-
const onLoad = async () => {
|
|
226
|
-
let temp: any = []
|
|
227
|
-
const messages = JSON.parse(await AsyncStorage.getItem('inngage') ?? '[]')
|
|
228
|
-
|
|
229
|
-
console.log("Messages saved on AsyncStorage: ", JSON.stringify(messages))
|
|
230
|
-
|
|
231
|
-
if (messages !== null) {
|
|
232
|
-
messages.forEach((el) => {
|
|
233
|
-
if (!isEmpty(el)) {
|
|
234
|
-
temp.push(el)
|
|
235
|
-
}
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
let msg: any = {}
|
|
239
|
-
if (temp.length > 0 && temp[0]?.data?.additional_data) {
|
|
240
|
-
msg = JSON.parse(temp[0].data.additional_data)
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (msg.background_img != '') {
|
|
244
|
-
setbgImage({ uri: msg.background_img })
|
|
245
|
-
} else {
|
|
246
|
-
setbgImage(undefined)
|
|
247
|
-
}
|
|
248
|
-
setData(temp)
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const handleClose = async () => {
|
|
253
|
-
if (props.onClose) {
|
|
254
|
-
if (props.onClose.toLowerCase() === 'clear') {
|
|
255
|
-
await AsyncStorage.removeItem('inngage');
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
setVisible(false)
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const handleBg = index => {
|
|
262
|
-
let msg = JSON.parse(data[index].data.additional_data)
|
|
263
|
-
if (msg.background_img != '') {
|
|
264
|
-
setbgImage({ uri: msg.background_img })
|
|
265
|
-
} else {
|
|
266
|
-
setbgImage(undefined)
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if (data.length > 0) {
|
|
271
|
-
return (
|
|
272
|
-
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
|
273
|
-
<Modal
|
|
274
|
-
animationType='slide'
|
|
275
|
-
visible={visible}
|
|
276
|
-
transparent={true}
|
|
277
|
-
style={{ justifyContent: 'center', alignItems: 'center', backgroundColor: 'blue' }}
|
|
278
|
-
><View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
|
279
|
-
<View style={[styles.styleContainer, props.styleContainer]}>
|
|
280
|
-
<ImageBackground style={{ width: '100%', alignItems: 'center', justifyContent: 'center' }} resizeMode='cover' imageStyle={{ borderRadius: 10, alignSelf: 'stretch', height: 480 }} source={bgImage}>
|
|
281
|
-
<TouchableHighlight
|
|
282
|
-
onPress={() => handleClose()}
|
|
283
|
-
underlayColor='#cccccc'
|
|
284
|
-
style={styles.closeButton}
|
|
285
|
-
>
|
|
286
|
-
<Text style={{ fontWeight: 'bold', color: '#ffffff' }}>
|
|
287
|
-
X
|
|
288
|
-
</Text>
|
|
289
|
-
</TouchableHighlight>
|
|
290
|
-
<Carousel
|
|
291
|
-
vertical
|
|
292
|
-
ref={CarouselRef}
|
|
293
|
-
layout={'default'}
|
|
294
|
-
layoutCardOffset={10}
|
|
295
|
-
data={data}
|
|
296
|
-
inactiveSlideOpacity={0}
|
|
297
|
-
containerCustomStyle={{
|
|
298
|
-
backgroundColor: 'white',
|
|
299
|
-
elevation: 10,
|
|
300
|
-
borderRadius: 10,
|
|
301
|
-
width: SLIDER_WIDTH * 0.8,
|
|
302
|
-
height: 480,
|
|
303
|
-
}}
|
|
304
|
-
contentContainerCustomStyle={{ justifyContent: 'center' }}
|
|
305
|
-
inactiveSlideShift={0}
|
|
306
|
-
onSnapToItem={(index) => {
|
|
307
|
-
handleBg(index)
|
|
308
|
-
}}
|
|
309
|
-
renderItem={({ item, index }) => _renderItem({ item, index })}
|
|
310
|
-
sliderHeight={500}
|
|
311
|
-
itemHeight={500}
|
|
312
|
-
/>
|
|
313
|
-
</ImageBackground>
|
|
314
|
-
</View>
|
|
315
|
-
</View>
|
|
316
|
-
</Modal>
|
|
317
|
-
</View>
|
|
318
|
-
);
|
|
319
|
-
} else {
|
|
320
|
-
return null
|
|
321
|
-
}
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
const styles = styleInapp({ SLIDER_WIDTH })
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import { Linking } from 'react-native'
|
|
2
|
-
import InAppBrowser from 'react-native-inappbrowser-reborn'
|
|
3
|
-
import messaging from '@react-native-firebase/messaging';
|
|
4
|
-
import { showAlert } from './utils'
|
|
5
|
-
import { notificationApi } from './services/inngage'
|
|
6
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
7
|
-
import PushNotification, { Importance } from 'react-native-push-notification'
|
|
8
|
-
|
|
9
|
-
export const linkInApp = (link: string) => {
|
|
10
|
-
InAppBrowser.open(link, {
|
|
11
|
-
dismissButtonStyle: 'cancel',
|
|
12
|
-
preferredBarTintColor: 'gray',
|
|
13
|
-
preferredControlTintColor: 'white',
|
|
14
|
-
readerMode: false,
|
|
15
|
-
showTitle: true,
|
|
16
|
-
toolbarColor: '#6200EE',
|
|
17
|
-
secondaryToolbarColor: 'black',
|
|
18
|
-
enableUrlBarHiding: true,
|
|
19
|
-
enableDefaultShare: true,
|
|
20
|
-
forceCloseOnRedirection: false,
|
|
21
|
-
animations: {
|
|
22
|
-
startEnter: 'slide_in_right',
|
|
23
|
-
startExit: 'slide_out_left',
|
|
24
|
-
endEnter: 'slide_in_right',
|
|
25
|
-
endExit: 'slide_out_left',
|
|
26
|
-
},
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const openLinkByType = (type: string, url: string) => {
|
|
31
|
-
const linkTypeHandlers: Record<string, () => void> = {
|
|
32
|
-
deep: () => Linking.openURL(url),
|
|
33
|
-
// inapp: () => linkInApp(url),
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const handler = linkTypeHandlers[type];
|
|
37
|
-
if (handler) {
|
|
38
|
-
handler();
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const openCommonNotification = ({ appToken, dev, remoteMessage, enableAlert, state }) => {
|
|
43
|
-
console.log("Notification Opened from", state)
|
|
44
|
-
|
|
45
|
-
if (!remoteMessage)
|
|
46
|
-
return
|
|
47
|
-
|
|
48
|
-
const { data } = remoteMessage
|
|
49
|
-
console.log("Data:", data)
|
|
50
|
-
if (!data || (data && !Object.keys(data).length))
|
|
51
|
-
return
|
|
52
|
-
|
|
53
|
-
const { notId, title, body, type, url } = data
|
|
54
|
-
const request = {
|
|
55
|
-
notificationRequest: {
|
|
56
|
-
id: notId,
|
|
57
|
-
app_token: appToken,
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (url) {
|
|
62
|
-
Linking.canOpenURL(url).then((supported) => {
|
|
63
|
-
if (supported) {
|
|
64
|
-
supported && openLinkByType(type, url)
|
|
65
|
-
}
|
|
66
|
-
}).catch(console.error)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return notificationApi(request, dev)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const handleUniqueRemoteMessage = async (
|
|
73
|
-
remoteMessage: { messageId?: string },
|
|
74
|
-
handleInitialNotification: (value: { messageId?: string }) => void
|
|
75
|
-
) => {
|
|
76
|
-
try {
|
|
77
|
-
const lastRemoteMessageId = await AsyncStorage.getItem('LAST_REMOTE_MESSAGE_ID');
|
|
78
|
-
const newRemoteMessageId = remoteMessage?.messageId;
|
|
79
|
-
|
|
80
|
-
if (newRemoteMessageId && lastRemoteMessageId !== newRemoteMessageId) {
|
|
81
|
-
await AsyncStorage.setItem('LAST_REMOTE_MESSAGE_ID', newRemoteMessageId);
|
|
82
|
-
handleInitialNotification(remoteMessage);
|
|
83
|
-
}
|
|
84
|
-
} catch (e) {
|
|
85
|
-
console.log(e);
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
export interface notificationsListenerProps {
|
|
90
|
-
appToken: string,
|
|
91
|
-
dev?: boolean,
|
|
92
|
-
enableAlert: boolean,
|
|
93
|
-
onNotificationOpenedApp?: any,
|
|
94
|
-
}
|
|
95
|
-
export default async ({ appToken, dev, enableAlert, onNotificationOpenedApp }: notificationsListenerProps) => {
|
|
96
|
-
var messageArray: any = [];
|
|
97
|
-
|
|
98
|
-
if (typeof onNotificationOpenedApp == 'function') {
|
|
99
|
-
messaging().getInitialNotification().then(async (value) => {
|
|
100
|
-
onNotificationOpenedApp(value?.data);
|
|
101
|
-
// console.log("Remote message ID:", value?.messageId)
|
|
102
|
-
if (value !== null)
|
|
103
|
-
handleUniqueRemoteMessage(value, async (value) => {
|
|
104
|
-
await handleInitialNotification(value);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const handleBackgroundMessage = async (remoteMessage: any) => {
|
|
110
|
-
console.log('Message handled in the background!', remoteMessage);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const handleNotificationOpenedApp = async (remoteMessage: any) => {
|
|
114
|
-
await openCommonNotification({ appToken, dev, remoteMessage, enableAlert, state: 'Background' })
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const handleInitialNotification = async (remoteMessage: any) => {
|
|
118
|
-
await openCommonNotification({ appToken, dev, remoteMessage, enableAlert, state: 'Closed' })
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const handleForegroundMessage = async (remoteMessage: any) => {
|
|
122
|
-
try {
|
|
123
|
-
PushNotification.configure({
|
|
124
|
-
onNotification: function (notification) {
|
|
125
|
-
console.log('LOCAL NOTIFICATION ==>', notification)
|
|
126
|
-
|
|
127
|
-
openCommonNotification({ appToken, dev, remoteMessage, enableAlert, state: 'Foreground' })
|
|
128
|
-
},
|
|
129
|
-
popInitialNotification: true,
|
|
130
|
-
requestPermissions: true
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
PushNotification.createChannel({
|
|
134
|
-
channelId: 'high_importance_channel',
|
|
135
|
-
channelName: 'default',
|
|
136
|
-
importance: Importance.HIGH,
|
|
137
|
-
playSound: true,
|
|
138
|
-
soundName: 'default',
|
|
139
|
-
vibrate: true
|
|
140
|
-
}, (created) => console.log(`createChannel returned '${created}'`));
|
|
141
|
-
|
|
142
|
-
} catch (e) {
|
|
143
|
-
console.error(e)
|
|
144
|
-
}
|
|
145
|
-
try {
|
|
146
|
-
PushNotification.localNotification({
|
|
147
|
-
autoCancel: true,
|
|
148
|
-
title: remoteMessage.data!.title,
|
|
149
|
-
message: remoteMessage.data!.body,
|
|
150
|
-
vibration: 300,
|
|
151
|
-
channelId: "high_importance_channel"
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
console.log('LOCAL NOTIFICATION : ')
|
|
155
|
-
console.log(remoteMessage)
|
|
156
|
-
} catch (e) {
|
|
157
|
-
console.error('LOCAL NOTIFICATION ERROR: ')
|
|
158
|
-
console.error(e)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (remoteMessage != null && remoteMessage.data!.additional_data) {
|
|
162
|
-
let msg = JSON.parse(remoteMessage.data!.additional_data)
|
|
163
|
-
if (msg.inapp_message == true) {
|
|
164
|
-
const currentMessages = await AsyncStorage.getItem('inngage');
|
|
165
|
-
if (currentMessages !== null) {
|
|
166
|
-
messageArray = JSON.parse(currentMessages);
|
|
167
|
-
}
|
|
168
|
-
messageArray.push(remoteMessage);
|
|
169
|
-
await AsyncStorage.setItem('inngage', JSON.stringify(messageArray));
|
|
170
|
-
}
|
|
171
|
-
} else if (remoteMessage != null && !remoteMessage.data!.additional_data) {
|
|
172
|
-
console.log(remoteMessage.data!.title)
|
|
173
|
-
if (enableAlert) {
|
|
174
|
-
showAlert(remoteMessage.data!.title, remoteMessage.data!.body)
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
messaging().setBackgroundMessageHandler(handleBackgroundMessage)
|
|
180
|
-
messaging().onNotificationOpenedApp(handleNotificationOpenedApp)
|
|
181
|
-
messaging().getInitialNotification().then(async (remoteMessage) => {
|
|
182
|
-
// console.log("Remote message ID:", remoteMessage?.messageId)
|
|
183
|
-
if (remoteMessage !== null)
|
|
184
|
-
handleUniqueRemoteMessage(remoteMessage, async (value) => {
|
|
185
|
-
await handleInitialNotification(value);
|
|
186
|
-
});
|
|
187
|
-
})
|
|
188
|
-
messaging().onMessage(handleForegroundMessage)
|
|
189
|
-
}
|
package/src/services/handler.ts
DELETED
|
@@ -1,42 +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 = (method, requestBody, path, isDev = false): Promise<Response> => {
|
|
34
|
-
return new Promise((resolve) => {
|
|
35
|
-
const url = String(baseUrlHook[isDev as any]).concat(path)
|
|
36
|
-
const request = requestConfigFactory(method, requestBody)
|
|
37
|
-
console.log(request)
|
|
38
|
-
fetch(url, request)
|
|
39
|
-
.then(resolve)
|
|
40
|
-
.catch(err => console.error('Fetch Error', err))
|
|
41
|
-
})
|
|
42
|
-
}
|
package/src/services/inngage.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { InngageProperties } from '../models/inngage_properties'
|
|
2
|
-
import { fetchClient } from './handler'
|
|
3
|
-
|
|
4
|
-
export const subscriptionApi = (request, dev = false) => {
|
|
5
|
-
if (InngageProperties.getDebugMode())
|
|
6
|
-
console.log('subscriptionApi', request)
|
|
7
|
-
return fetchClient('POST', request, '/subscription/', !!dev)
|
|
8
|
-
}
|
|
9
|
-
export const notificationApi = (request, dev = false) => {
|
|
10
|
-
if (InngageProperties.getDebugMode())
|
|
11
|
-
console.log('notificationApi', request)
|
|
12
|
-
return fetchClient('POST', request, '/notification/', !!dev)
|
|
13
|
-
}
|
|
14
|
-
export const eventsApi = (request, dev = false) => {
|
|
15
|
-
if (InngageProperties.getDebugMode())
|
|
16
|
-
console.log('eventsApi', request)
|
|
17
|
-
return fetchClient('POST', request, '/events/newEvent/', !!dev)
|
|
18
|
-
}
|
|
19
|
-
export const addUserDataApi = (request, dev = false) => {
|
|
20
|
-
if (InngageProperties.getDebugMode())
|
|
21
|
-
console.log('addUserData', request)
|
|
22
|
-
return fetchClient('POST', request, '/subscription/addCustomField', !!dev)
|
|
23
|
-
}
|