@inngageregistry/inngage-react 4.0.0-alpha.3 → 4.0.0-beta.2
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/README.md +32 -11
- package/package.json +1 -1
- package/src/Inngage.ts +3 -4
- package/src/api/handler.ts +39 -39
- package/src/components/in_app.tsx +166 -132
- package/src/components/styles.ts +31 -13
- package/src/firebase/notifications_listener.ts +78 -10
- package/src/index.ts +6 -3
- package/src/services/handler.ts +41 -0
- package/src/services/inngage.ts +23 -0
- /package/src/services/{api_service.ts → api_services.ts} +0 -0
package/README.md
CHANGED
|
@@ -18,23 +18,44 @@
|
|
|
18
18
|
</div>
|
|
19
19
|
|
|
20
20
|
## Instalação
|
|
21
|
-
###
|
|
21
|
+
### Ambiente de desenvolvimento
|
|
22
|
+
Antes de começar a utilizar nossa SDK, instale as dependências externas utilizadas:
|
|
22
23
|
```bash
|
|
23
24
|
"dependencies": {
|
|
24
25
|
"@react-native-async-storage/async-storage": "^1.18.1",
|
|
26
|
+
"@react-native-community/push-notification-ios": "^1.11.0",
|
|
25
27
|
"@react-native-firebase/app": "^17.4.2",
|
|
26
28
|
"@react-native-firebase/messaging": "^17.4.2",
|
|
27
29
|
"react-native-device-info": "^10.6.0",
|
|
28
|
-
"react-native-inappbrowser-reborn": "^3.7.0",
|
|
29
30
|
"react-native-localize": "^2.2.6",
|
|
30
|
-
"react-native-
|
|
31
|
+
"react-native-permissions": "^3.8.0",
|
|
32
|
+
"react-native-push-notification": "^8.1.1",
|
|
33
|
+
"react-native-inappbrowser-reborn": "^3.7.0",
|
|
31
34
|
}
|
|
32
35
|
```
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
> 📘 *Recomendação*: Certifique-se de instalar as versões conforme especificado nesta documentação. Para a dependência react-native-inappbrowser-reborn, siga as instruções da seção "Getting Started" na documentação oficial para garantir o funcionamento adequado na abertura de URLs do tipo Weblink. Consulte o link a seguir para mais detalhes:
|
|
37
|
+
>
|
|
38
|
+
> <https://www.npmjs.com/package/react-native-inappbrowser-reborn>
|
|
39
|
+
|
|
40
|
+
### Importando o FCM Token (API Key)
|
|
41
|
+
Para aproveitar nossa SDK, será necessário importar o FCM Token (API Key) do seu projeto Firebase em nossa plataforma. Siga o passo a passo neste [link]("https://inngage.readme.io/docs/firebase-console#configura%C3%A7%C3%B5es-do-projeto-firebase") para executar essa ação.
|
|
42
|
+
|
|
43
|
+
### Instalando o package utilizando o NPM ou YARN
|
|
44
|
+
|
|
45
|
+
Para adicionar a SDK da Inngage ao seu projeto, execute o seguinte comando utilizando o NPM:
|
|
46
|
+
```
|
|
47
|
+
npm i @inngageregistry/inngage-react
|
|
48
|
+
```
|
|
49
|
+
Este comando adiciona a seguinte linha no arquivo _package.json_ de seu pacote:
|
|
50
|
+
```
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@inngageregistry/inngage-react": "^4.0.0-beta.2",
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
> 📘 Se a instalação via `npm` não funcionar corretamente, você pode instalar a dependência utilizando o `yarn`.
|
|
56
|
+
> 📘
|
|
57
|
+
|
|
58
|
+
Para instalar a SDK com o yarn, siga os passos abaixo:
|
|
59
|
+
|
|
60
|
+
1. No arquivo `package.json`, adicione a seguinte dependência em `dependencies`: **"@inngageregistry/inngage-react": "^4.0.0-beta.2"**.
|
|
61
|
+
2. No terminal, dentro da pasta do seu projeto, execute o comando: **yarn install**. Isso irá instalar a SDK corretamente.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inngageregistry/inngage-react",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-beta.2",
|
|
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
|
@@ -4,12 +4,12 @@ import * as RNLocalize from "react-native-localize";
|
|
|
4
4
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
5
5
|
|
|
6
6
|
import { formatDate } from "./utils";
|
|
7
|
-
import { InngageNotificationMessage } from "./firebase/notifications_listener";
|
|
7
|
+
import { InngageNotificationMessage, messagingHeadlessTask } from "./firebase/notifications_listener";
|
|
8
8
|
import { InngageProperties } from './models/inngage_properties';
|
|
9
9
|
|
|
10
10
|
import RNPermissions, { NotificationOption, RESULTS } from 'react-native-permissions';
|
|
11
11
|
|
|
12
|
-
import ApiService from './services/
|
|
12
|
+
import ApiService from './services/api_services';
|
|
13
13
|
|
|
14
14
|
const API_LEVEL_33 = 33;
|
|
15
15
|
|
|
@@ -57,7 +57,6 @@ const getFirebaseToken = async () => {
|
|
|
57
57
|
|
|
58
58
|
interface SubscriptionProps {
|
|
59
59
|
appToken: string,
|
|
60
|
-
enableAlert: boolean,
|
|
61
60
|
dev?: boolean,
|
|
62
61
|
friendlyIdentifier?: string,
|
|
63
62
|
customFields?: any,
|
|
@@ -90,7 +89,7 @@ class Inngage {
|
|
|
90
89
|
return Inngage.instance;
|
|
91
90
|
}
|
|
92
91
|
|
|
93
|
-
static
|
|
92
|
+
static notificationListener(firebaseListenCallback?: any) {
|
|
94
93
|
try {
|
|
95
94
|
InngageNotificationMessage(firebaseListenCallback)
|
|
96
95
|
} catch (e) {
|
package/src/api/handler.ts
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
1
|
const baseUrlHook = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
6
|
}
|
|
7
7
|
|
|
8
8
|
const requestConfigFactory = (method, request) => {
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
|
20
28
|
}
|
|
21
|
-
} catch (e) {
|
|
22
|
-
console.error(e)
|
|
23
|
-
}
|
|
24
|
-
let objToSend = {
|
|
25
|
-
method,
|
|
26
|
-
body: JSON.stringify(request),
|
|
27
|
-
headers: header
|
|
28
|
-
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
return objToSend
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export const fetchClient = async (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
method: string,
|
|
35
|
+
requestBody: any,
|
|
36
|
+
path: string,
|
|
37
|
+
isDev = false
|
|
38
38
|
): Promise<Response> => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
throw new Error(`Network response was not ok (${response.status})`);
|
|
46
|
+
}
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
return response;
|
|
49
|
+
} catch (error: any) {
|
|
50
|
+
console.error('Fetch Error:', error.message);
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
53
|
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
StyleSheet,
|
|
4
|
+
Image,
|
|
5
|
+
View,
|
|
6
|
+
Text,
|
|
7
|
+
TouchableOpacity,
|
|
8
|
+
ImageBackground,
|
|
9
|
+
Dimensions,
|
|
10
|
+
Linking,
|
|
10
11
|
} from "react-native";
|
|
11
12
|
|
|
12
13
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
@@ -16,143 +17,176 @@ import { buildStyles } from "./styles";
|
|
|
16
17
|
import { Modal } from "../components/modal";
|
|
17
18
|
import { InngageProperties } from "../models/inngage_properties";
|
|
18
19
|
|
|
20
|
+
import InAppBrowser from 'react-native-inappbrowser-reborn';
|
|
21
|
+
|
|
19
22
|
interface InAppData {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
23
|
+
inapp_message: boolean
|
|
24
|
+
title: string
|
|
25
|
+
body: string
|
|
26
|
+
title_font_color: string
|
|
27
|
+
body_font_color: string
|
|
28
|
+
background_color: string
|
|
29
|
+
btn_left_txt_color: string
|
|
30
|
+
btn_left_bg_color: string
|
|
31
|
+
btn_right_txt_color: string
|
|
32
|
+
btn_right_bg_color: string
|
|
33
|
+
background_image: string
|
|
34
|
+
btn_left_txt: string
|
|
35
|
+
btn_left_action_type: string
|
|
36
|
+
btn_left_action_link: string
|
|
37
|
+
btn_right_txt: string
|
|
38
|
+
btn_right_action_type: string
|
|
39
|
+
btn_right_action_link: string
|
|
40
|
+
rich_content: string
|
|
41
|
+
inpression: string
|
|
42
|
+
bg_img_action_type: string
|
|
43
|
+
bg_img_action_link: string
|
|
44
|
+
dot_color: string
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
interface InAppRichContent {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
carousel: boolean
|
|
49
|
+
img1: string
|
|
50
|
+
img2: string
|
|
51
|
+
img3: string
|
|
52
|
+
img4: string
|
|
53
|
+
img5: string
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
interface InAppProps {
|
|
54
|
-
|
|
57
|
+
onDismiss: () => void;
|
|
55
58
|
}
|
|
56
59
|
|
|
57
|
-
export function InApp(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
60
|
+
export function InApp({ onDismiss }: InAppProps): JSX.Element {
|
|
61
|
+
const { width: screenWidth } = Dimensions.get('window');
|
|
62
|
+
|
|
63
|
+
const sliderWidth = screenWidth;
|
|
64
|
+
const itemWidth = screenWidth * 0.9;
|
|
65
|
+
|
|
66
|
+
const [data, setData] = React.useState<InAppData>();
|
|
67
|
+
const [richContent, setRichContent] = React.useState<InAppRichContent>();
|
|
68
|
+
const [visible, setVisible] = React.useState(false);
|
|
69
|
+
|
|
70
|
+
React.useEffect(() => {
|
|
71
|
+
const fetchAdditionalData = async () => {
|
|
72
|
+
try {
|
|
73
|
+
console.log('in app message')
|
|
74
|
+
const data = await AsyncStorage.getItem('inapp');
|
|
75
|
+
console.log(data)
|
|
76
|
+
if (data) {
|
|
77
|
+
const parsedData = JSON.parse(data);
|
|
78
|
+
const richContentData = parsedData.rich_content;
|
|
79
|
+
|
|
80
|
+
setVisible(true);
|
|
81
|
+
setData(parsedData);
|
|
82
|
+
setRichContent(richContentData);
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error('Error retrieving additionalData from AsyncStorage:', error);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
fetchAdditionalData();
|
|
90
|
+
}, []);
|
|
91
|
+
|
|
92
|
+
const styles = buildStyles(data, screenWidth * 0.9);
|
|
93
|
+
|
|
94
|
+
const handleDismissInApp = async () => {
|
|
95
|
+
await AsyncStorage.removeItem('inapp');
|
|
96
|
+
setVisible(false);
|
|
97
|
+
onDismiss();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const handleClick = async (link, type) => {
|
|
101
|
+
if (type === 'inapp') {
|
|
102
|
+
try {
|
|
103
|
+
if (await InAppBrowser.isAvailable()) {
|
|
104
|
+
await InAppBrowser.open(link, {
|
|
105
|
+
dismissButtonStyle: 'close',
|
|
106
|
+
preferredBarTintColor: '#453AA4',
|
|
107
|
+
preferredControlTintColor: 'white',
|
|
108
|
+
enableDefaultShare: true,
|
|
109
|
+
enableBarCollapsing: true,
|
|
110
|
+
});
|
|
111
|
+
} else {
|
|
112
|
+
Linking.openURL(link);
|
|
113
|
+
}
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error(error);
|
|
116
|
+
}
|
|
117
|
+
} else if (type === 'deep') {
|
|
118
|
+
Linking.openURL(link).catch((err) =>
|
|
119
|
+
console.error('Erro ao abrir o link:', err)
|
|
120
|
+
);
|
|
79
121
|
}
|
|
80
|
-
} catch (error) {
|
|
81
|
-
console.error('Error retrieving additionalData from AsyncStorage:', error);
|
|
82
|
-
}
|
|
83
122
|
};
|
|
84
123
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
124
|
+
const imageUrls: string[] = [
|
|
125
|
+
richContent?.img1 ?? '',
|
|
126
|
+
richContent?.img2 ?? '',
|
|
127
|
+
richContent?.img3 ?? '',
|
|
128
|
+
richContent?.img4 ?? '',
|
|
129
|
+
richContent?.img5 ?? ''
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
const stylesCarousel = StyleSheet.create({
|
|
133
|
+
itemContainer: {
|
|
134
|
+
justifyContent: 'center',
|
|
135
|
+
height: 250
|
|
136
|
+
},
|
|
137
|
+
itemImg: {
|
|
138
|
+
height: 250,
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const _renderItem = ({ item, index }) => {
|
|
143
|
+
return (
|
|
144
|
+
<View style={stylesCarousel.itemContainer}>
|
|
145
|
+
<Image style={[stylesCarousel.itemImg]} source={{ uri: item }} />
|
|
146
|
+
</View>
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (InngageProperties.getDebugMode() && data != null) {
|
|
151
|
+
console.log('INNGAGE - Data In App:', data)
|
|
152
|
+
console.log('INNGAGE - Data Rich Content:', richContent)
|
|
153
|
+
}
|
|
154
|
+
|
|
114
155
|
return (
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
156
|
+
<Modal
|
|
157
|
+
onBackdropPress={handleDismissInApp}
|
|
158
|
+
renderToHardwareTextureAndroid={true}
|
|
159
|
+
transparent={true}
|
|
160
|
+
visible={visible}>
|
|
161
|
+
<ImageBackground style={styles.content} source={{ uri: data?.background_image }}>
|
|
162
|
+
{richContent?.carousel ? <Carousel
|
|
163
|
+
layout={"default"}
|
|
164
|
+
data={imageUrls}
|
|
165
|
+
sliderWidth={sliderWidth}
|
|
166
|
+
itemWidth={itemWidth}
|
|
167
|
+
renderItem={_renderItem} /> : null}
|
|
168
|
+
<TouchableOpacity style={styles.closeButton} onPress={handleDismissInApp}>
|
|
169
|
+
<Text style={styles.textButton}>X</Text>
|
|
170
|
+
</TouchableOpacity>
|
|
171
|
+
<View style={styles.messageData}>
|
|
172
|
+
<Text style={styles.title}>{data?.title}</Text>
|
|
173
|
+
<Text style={styles.body}>{data?.body}</Text>
|
|
174
|
+
</View>
|
|
175
|
+
<View style={styles.footer}>
|
|
176
|
+
{data?.btn_left_txt != null ?
|
|
177
|
+
<TouchableOpacity
|
|
178
|
+
style={styles.buttonLeft}
|
|
179
|
+
onPress={() => handleClick(data?.btn_left_action_link, data?.btn_left_action_type)}>
|
|
180
|
+
<Text style={styles.textButtonLeft}>{data?.btn_left_txt}</Text>
|
|
181
|
+
</TouchableOpacity> : null}
|
|
182
|
+
{data?.btn_right_txt != null ?
|
|
183
|
+
<TouchableOpacity
|
|
184
|
+
style={styles.buttonRight}
|
|
185
|
+
onPress={() => handleClick(data?.btn_right_action_link, data?.btn_right_action_type)}>
|
|
186
|
+
<Text style={styles.textButtonRight}>{data?.btn_right_txt}</Text>
|
|
187
|
+
</TouchableOpacity> : null}
|
|
188
|
+
</View>
|
|
189
|
+
</ImageBackground>
|
|
190
|
+
</Modal>
|
|
118
191
|
)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (InngageProperties.getDebugMode() && data != null) {
|
|
122
|
-
console.log('INNGAGE - Data In App:', data)
|
|
123
|
-
console.log('INNGAGE - Data Rich Content:', richContent)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return (
|
|
127
|
-
<Modal
|
|
128
|
-
renderToHardwareTextureAndroid={true}
|
|
129
|
-
transparent={true}
|
|
130
|
-
visible={visible}>
|
|
131
|
-
<ImageBackground style={styles.content} source={{ uri: data?.background_image }}>
|
|
132
|
-
{richContent?.carousel ? <Carousel
|
|
133
|
-
layout={"default"}
|
|
134
|
-
data={imageUrls}
|
|
135
|
-
sliderWidth={sliderWidth}
|
|
136
|
-
itemWidth={itemWidth}
|
|
137
|
-
renderItem={_renderItem} /> : null}
|
|
138
|
-
<TouchableOpacity style={styles.closeButton} onPress={handleDismissInApp}>
|
|
139
|
-
<Text>X</Text>
|
|
140
|
-
</TouchableOpacity>
|
|
141
|
-
<View style={styles.messageData}>
|
|
142
|
-
<Text style={styles.title}>{data?.title}</Text>
|
|
143
|
-
<Text style={styles.body}>{data?.body}</Text>
|
|
144
|
-
</View>
|
|
145
|
-
<View style={styles.footer}>
|
|
146
|
-
{data?.btn_left_txt != null ? <TouchableOpacity
|
|
147
|
-
style={styles.buttonLeft}>
|
|
148
|
-
<Text style={styles.textButton}>{data?.btn_left_txt}</Text>
|
|
149
|
-
</TouchableOpacity> : null}
|
|
150
|
-
{data?.btn_right_txt != null ? <TouchableOpacity
|
|
151
|
-
style={styles.buttonRight}>
|
|
152
|
-
<Text style={styles.textButton}>{data?.btn_right_txt}</Text>
|
|
153
|
-
</TouchableOpacity> : null}
|
|
154
|
-
</View>
|
|
155
|
-
</ImageBackground>
|
|
156
|
-
</Modal>
|
|
157
|
-
)
|
|
158
192
|
}
|
package/src/components/styles.ts
CHANGED
|
@@ -3,15 +3,29 @@ import { PlatformColor, StyleSheet } from "react-native";
|
|
|
3
3
|
|
|
4
4
|
export const buildStyles = (data: any, screen: any) => StyleSheet.create({
|
|
5
5
|
closeButton: {
|
|
6
|
+
width: 30,
|
|
7
|
+
height: 30,
|
|
8
|
+
justifyContent: 'center',
|
|
9
|
+
alignItems: 'center',
|
|
10
|
+
backgroundColor: 'transparent', // Cor do botão
|
|
11
|
+
borderRadius: 25, // Torna o botão circular
|
|
12
|
+
shadowOffset: { width: 0, height: 2 },
|
|
13
|
+
shadowOpacity: 0.2,
|
|
14
|
+
shadowRadius: 4,
|
|
6
15
|
position: 'absolute',
|
|
7
16
|
top: 10,
|
|
8
17
|
right: 10,
|
|
9
18
|
zIndex: 10,
|
|
10
19
|
},
|
|
20
|
+
textButton: {
|
|
21
|
+
color: '#000', // Cor do texto "X"
|
|
22
|
+
fontSize: 16, // Tamanho do "X"
|
|
23
|
+
fontWeight: 'bold', // Deixa o "X" em negrito
|
|
24
|
+
},
|
|
11
25
|
content: {
|
|
12
26
|
backgroundColor: data?.background_color,
|
|
13
27
|
flexDirection: "column",
|
|
14
|
-
borderRadius:
|
|
28
|
+
borderRadius: 20,
|
|
15
29
|
paddingBottom: 16,
|
|
16
30
|
paddingRight: 16,
|
|
17
31
|
paddingLeft: 16,
|
|
@@ -21,7 +35,11 @@ export const buildStyles = (data: any, screen: any) => StyleSheet.create({
|
|
|
21
35
|
width: screen,
|
|
22
36
|
alignItems: "center"
|
|
23
37
|
},
|
|
24
|
-
messageData: {
|
|
38
|
+
messageData: {
|
|
39
|
+
marginTop: 12,
|
|
40
|
+
alignItems: "center",
|
|
41
|
+
justifyContent: "center",
|
|
42
|
+
},
|
|
25
43
|
footer: {
|
|
26
44
|
flexDirection: "row",
|
|
27
45
|
alignItems: "center",
|
|
@@ -29,16 +47,12 @@ export const buildStyles = (data: any, screen: any) => StyleSheet.create({
|
|
|
29
47
|
marginTop: 4,
|
|
30
48
|
},
|
|
31
49
|
title: {
|
|
32
|
-
color:
|
|
33
|
-
`@android:color/${"primary_text_light"}`
|
|
34
|
-
),
|
|
50
|
+
color: data?.title_font_color,
|
|
35
51
|
fontWeight: "500",
|
|
36
52
|
fontSize: 18,
|
|
37
53
|
},
|
|
38
54
|
body: {
|
|
39
|
-
color:
|
|
40
|
-
`@android:color/${"secondary_text_light"}`
|
|
41
|
-
),
|
|
55
|
+
color: data?.body_font_color,
|
|
42
56
|
fontSize: 16,
|
|
43
57
|
marginTop: 10,
|
|
44
58
|
marginBottom: 10,
|
|
@@ -57,14 +71,18 @@ export const buildStyles = (data: any, screen: any) => StyleSheet.create({
|
|
|
57
71
|
justifyContent: "center",
|
|
58
72
|
alignItems: "center",
|
|
59
73
|
},
|
|
60
|
-
|
|
61
|
-
color:
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
textButtonLeft: {
|
|
75
|
+
color: data?.btn_left_txt_color,
|
|
76
|
+
textAlign: "center",
|
|
77
|
+
backgroundColor: "transparent",
|
|
78
|
+
padding: 8,
|
|
79
|
+
fontSize: 14,
|
|
80
|
+
},
|
|
81
|
+
textButtonRight: {
|
|
82
|
+
color: data?.btn_right_txt_color,
|
|
64
83
|
textAlign: "center",
|
|
65
84
|
backgroundColor: "transparent",
|
|
66
85
|
padding: 8,
|
|
67
86
|
fontSize: 14,
|
|
68
|
-
textTransform: "uppercase",
|
|
69
87
|
},
|
|
70
88
|
})
|
|
@@ -1,29 +1,71 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
4
4
|
|
|
5
5
|
import messaging from '@react-native-firebase/messaging';
|
|
6
|
+
import PushNotificationIOS from "@react-native-community/push-notification-ios";
|
|
6
7
|
import PushNotification, { Importance } from 'react-native-push-notification'
|
|
7
8
|
|
|
8
9
|
import { InngageProperties } from '../models/inngage_properties';
|
|
9
|
-
import * as ApiService from '../services/
|
|
10
|
+
import * as ApiService from '../services/api_services'
|
|
11
|
+
import { AppState, Linking } from 'react-native';
|
|
12
|
+
import InAppBrowser from 'react-native-inappbrowser-reborn';
|
|
10
13
|
|
|
11
14
|
export const messagingHeadlessTask = () => {
|
|
12
15
|
return messaging().setBackgroundMessageHandler(async remoteMessage => {
|
|
13
16
|
if (InngageProperties.getDebugMode())
|
|
14
|
-
console.log('INNGAGE
|
|
15
|
-
|
|
17
|
+
console.log('INNGAGE BACKGROUND AND CLOSED DATA: ', remoteMessage)
|
|
18
|
+
|
|
19
|
+
if (remoteMessage?.data?.additional_data != null) {
|
|
16
20
|
await AsyncStorage.setItem('inapp', remoteMessage?.data?.additional_data);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return Promise.resolve();
|
|
17
24
|
});
|
|
18
25
|
}
|
|
19
26
|
|
|
27
|
+
export const useInAppHandler = () => {
|
|
28
|
+
const [showInApp, setShowInApp] = useState(false);
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const checkInAppData = async () => {
|
|
32
|
+
const inAppData = await AsyncStorage.getItem('inapp');
|
|
33
|
+
if (inAppData) {
|
|
34
|
+
setShowInApp(true);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
checkInAppData();
|
|
39
|
+
|
|
40
|
+
const subscription = AppState.addEventListener('change', nextAppState => {
|
|
41
|
+
if (nextAppState === 'active') {
|
|
42
|
+
checkInAppData();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return () => {
|
|
47
|
+
subscription.remove();
|
|
48
|
+
};
|
|
49
|
+
}, []);
|
|
50
|
+
|
|
51
|
+
return { showInApp, setShowInApp };
|
|
52
|
+
}
|
|
53
|
+
|
|
20
54
|
export const InngageNotificationMessage = (firebaseListenCallback?: any) => {
|
|
55
|
+
const [notificationMessage, setNotificationMessage] = useState(null);
|
|
56
|
+
|
|
21
57
|
useEffect(() => {
|
|
22
58
|
PushNotification.configure({
|
|
59
|
+
onAction: function (data: any) {
|
|
60
|
+
console.log(data)
|
|
61
|
+
},
|
|
23
62
|
onNotification: function (data: any) {
|
|
24
63
|
if (data.foreground) {
|
|
25
|
-
|
|
64
|
+
if (notificationMessage) {
|
|
65
|
+
handleNotification(notificationMessage)
|
|
66
|
+
}
|
|
26
67
|
}
|
|
68
|
+
data.finish(PushNotificationIOS.FetchResult.NoData);
|
|
27
69
|
},
|
|
28
70
|
popInitialNotification: true,
|
|
29
71
|
requestPermissions: true
|
|
@@ -45,12 +87,17 @@ export const InngageNotificationMessage = (firebaseListenCallback?: any) => {
|
|
|
45
87
|
const handleMessage = async (remoteMessage: any) => {
|
|
46
88
|
const notificationData = remoteMessage.data;
|
|
47
89
|
|
|
90
|
+
if (notificationData.additional_data != null)
|
|
91
|
+
await AsyncStorage.setItem('inapp', notificationData.additional_data);
|
|
92
|
+
|
|
48
93
|
if (InngageProperties.getDebugMode())
|
|
49
94
|
console.log('Remote message received in foreground: ', remoteMessage);
|
|
50
95
|
|
|
51
96
|
if (firebaseListenCallback != null && remoteMessage != null)
|
|
52
97
|
firebaseListenCallback(notificationData)
|
|
53
98
|
|
|
99
|
+
setNotificationMessage(remoteMessage);
|
|
100
|
+
|
|
54
101
|
PushNotification.localNotification({
|
|
55
102
|
autoCancel: true,
|
|
56
103
|
bigPictureUrl: remoteMessage.notification?.android?.imageUrl,
|
|
@@ -60,10 +107,6 @@ export const InngageNotificationMessage = (firebaseListenCallback?: any) => {
|
|
|
60
107
|
vibration: 300,
|
|
61
108
|
channelId: "channel_id",
|
|
62
109
|
});
|
|
63
|
-
|
|
64
|
-
if (notificationData.additional_data != null)
|
|
65
|
-
await AsyncStorage.setItem('inapp', notificationData.additional_data);
|
|
66
|
-
|
|
67
110
|
};
|
|
68
111
|
|
|
69
112
|
return messaging().onMessage(handleMessage);
|
|
@@ -80,7 +123,6 @@ export const InngageNotificationMessage = (firebaseListenCallback?: any) => {
|
|
|
80
123
|
|
|
81
124
|
useEffect(() => {
|
|
82
125
|
messaging().getInitialNotification().then(async (value) => {
|
|
83
|
-
|
|
84
126
|
if (value !== null)
|
|
85
127
|
handleUniqueRemoteMessage(value);
|
|
86
128
|
});
|
|
@@ -89,6 +131,7 @@ export const InngageNotificationMessage = (firebaseListenCallback?: any) => {
|
|
|
89
131
|
const handleUniqueRemoteMessage = async (
|
|
90
132
|
remoteMessage: { messageId?: string }) => {
|
|
91
133
|
try {
|
|
134
|
+
console.log('oi')
|
|
92
135
|
const lastRemoteMessageId = await AsyncStorage.getItem('LAST_REMOTE_MESSAGE_ID');
|
|
93
136
|
const newRemoteMessageId = remoteMessage?.messageId;
|
|
94
137
|
|
|
@@ -109,6 +152,31 @@ export const InngageNotificationMessage = (firebaseListenCallback?: any) => {
|
|
|
109
152
|
app_token: InngageProperties.appToken,
|
|
110
153
|
}
|
|
111
154
|
};
|
|
155
|
+
|
|
156
|
+
if (remoteMessage.data?.url) {
|
|
157
|
+
if (remoteMessage.data?.type === 'inapp') {
|
|
158
|
+
try {
|
|
159
|
+
if (await InAppBrowser.isAvailable()) {
|
|
160
|
+
await InAppBrowser.open(remoteMessage.data?.url, {
|
|
161
|
+
dismissButtonStyle: 'close',
|
|
162
|
+
preferredBarTintColor: '#453AA4',
|
|
163
|
+
preferredControlTintColor: 'white',
|
|
164
|
+
enableDefaultShare: true,
|
|
165
|
+
enableBarCollapsing: true,
|
|
166
|
+
});
|
|
167
|
+
} else {
|
|
168
|
+
Linking.openURL(remoteMessage.data?.url);
|
|
169
|
+
}
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.error(error);
|
|
172
|
+
}
|
|
173
|
+
} else if (remoteMessage.data?.type === 'deep') {
|
|
174
|
+
Linking.openURL(remoteMessage.data?.url).catch((err) =>
|
|
175
|
+
console.error('Erro ao abrir o link:', err)
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
112
180
|
await ApiService.sendNotification(request);
|
|
113
181
|
}
|
|
114
182
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { InApp } from './components/in_app';
|
|
2
|
+
import { useInAppHandler, messagingHeadlessTask } from './firebase/notifications_listener'
|
|
2
3
|
import Inngage from './Inngage';
|
|
3
4
|
|
|
4
|
-
//-------------- In-APP Component -------------//
|
|
5
5
|
export { InApp };
|
|
6
|
-
|
|
7
|
-
//-------------- Inngage Wrapper --------------//
|
|
6
|
+
export { useInAppHandler, messagingHeadlessTask }
|
|
8
7
|
export default Inngage;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
fetch(url, request)
|
|
38
|
+
.then(resolve)
|
|
39
|
+
.catch(err => console.error('Fetch Error', err))
|
|
40
|
+
})
|
|
41
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
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
|
+
}
|
|
File without changes
|