@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 CHANGED
@@ -18,23 +18,44 @@
18
18
  </div>
19
19
 
20
20
  ## Instalação
21
- ### Instalando as dependências
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-snap-carousel": "^3.9.1"
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
- Ao adicioná-las no seu ```package.json```, utilize o comando ```npm install```.
34
- ### Importar FCM Token (API Key)
35
- Para aproveitar nossos SDKs, será necessário importar o FCM Token (API Key) do seu projeto Firebase em nossa plataforma.
36
- ### Instalando a SDK
37
- Utilize o NPM:
38
- ```bash
39
- $ npm i @inngageregistry/inngage-react
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-alpha.3",
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/api_service';
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 async notificationListener(firebaseListenCallback?: any) {
92
+ static notificationListener(firebaseListenCallback?: any) {
94
93
  try {
95
94
  InngageNotificationMessage(firebaseListenCallback)
96
95
  } catch (e) {
@@ -1,53 +1,53 @@
1
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',
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
- 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
- }
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
- return objToSend
30
+ return objToSend
31
31
  }
32
32
 
33
33
  export const fetchClient = async (
34
- method: string,
35
- requestBody: any,
36
- path: string,
37
- isDev = false
34
+ method: string,
35
+ requestBody: any,
36
+ path: string,
37
+ isDev = false
38
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);
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
- if (!response.ok) {
45
- throw new Error(`Network response was not ok (${response.status})`);
46
- }
44
+ if (!response.ok) {
45
+ throw new Error(`Network response was not ok (${response.status})`);
46
+ }
47
47
 
48
- return response;
49
- } catch (error: any) {
50
- console.error('Fetch Error:', error.message);
51
- throw error;
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
- StyleSheet,
4
- Image,
5
- View,
6
- Text,
7
- TouchableOpacity,
8
- ImageBackground,
9
- Dimensions,
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
- 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
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
- carousel: boolean
46
- img1: string
47
- img2: string
48
- img3: string
49
- img4: string
50
- img5: string
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(props: 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);
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
- 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
- }
94
-
95
- const imageUrls: string[] = [
96
- richContent?.img1 ?? '',
97
- richContent?.img2 ?? '',
98
- richContent?.img3 ?? '',
99
- richContent?.img4 ?? '',
100
- richContent?.img5 ?? ''
101
- ];
102
-
103
- const stylesCarousel = StyleSheet.create({
104
- itemContainer: {
105
- justifyContent: 'center',
106
- height: 250
107
- },
108
- itemImg: {
109
- height: 250,
110
- },
111
- });
112
-
113
- const _renderItem = ({ item, index }) => {
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
- <View style={stylesCarousel.itemContainer}>
116
- <Image style={[props, stylesCarousel.itemImg]} source={{ uri: item }} />
117
- </View>
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
  }
@@ -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: 3,
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: { marginTop: 12 },
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: PlatformColor(
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: PlatformColor(
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
- textButton: {
61
- color: PlatformColor(
62
- `@android:color/${"secondary_text_light"}`
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/api_service'
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 - Data in background and closed app: ', remoteMessage)
15
- if (remoteMessage?.data?.additional_data != null)
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
- handleNotification(data)
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
+ }