@inngageregistry/inngage-react 3.3.1 → 4.0.0-alpha.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.
@@ -0,0 +1,221 @@
1
+ import * as React from "react";
2
+ import {
3
+ Animated, Easing,
4
+ Modal as ReactNativeModal,
5
+ ModalProps as ReactNativeModalProps,
6
+ Platform,
7
+ StyleProp,
8
+ StyleSheet,
9
+ TouchableWithoutFeedback,
10
+ ViewStyle
11
+ } from "react-native";
12
+ import { Component } from "react";
13
+
14
+ const MODAL_ANIM_DURATION = 300;
15
+ const MODAL_BACKDROP_OPACITY = 0.3;
16
+
17
+ const CONTENT_ANIMATION_IN = Platform.select({
18
+ ios: {
19
+ opacity: {
20
+ inputRange: [0, 1],
21
+ outputRange: [0, 1],
22
+ },
23
+ scale: {
24
+ inputRange: [0, 0.5, 1],
25
+ outputRange: [1.2, 1.1, 1],
26
+ },
27
+ },
28
+ android: {
29
+ opacity: {
30
+ inputRange: [0, 0.5, 1],
31
+ outputRange: [0, 1, 1],
32
+ },
33
+ scale: {
34
+ inputRange: [0, 1],
35
+ outputRange: [0.3, 1],
36
+ },
37
+ },
38
+ default: {
39
+ opacity: {
40
+ inputRange: [0, 0.5, 1],
41
+ outputRange: [0, 1, 1],
42
+ },
43
+ scale: {
44
+ inputRange: [0, 1],
45
+ outputRange: [0.3, 1],
46
+ },
47
+ },
48
+ });
49
+
50
+ const CONTENT_ANIMATION_OUT = Platform.select({
51
+ default: {
52
+ opacity: {
53
+ inputRange: [0, 1],
54
+ outputRange: [0, 1],
55
+ },
56
+ },
57
+ });
58
+
59
+ export interface ModalProps extends ReactNativeModalProps {
60
+ onBackdropPress?: () => void;
61
+ onHide?: () => void;
62
+ visible?: boolean;
63
+ contentStyle?: StyleProp<ViewStyle>;
64
+ useNativeDriver?: boolean;
65
+ }
66
+
67
+ interface ModalState {
68
+ visible: boolean;
69
+ currentAnimation: "none" | "in" | "out";
70
+ }
71
+
72
+ export class Modal extends Component<ModalProps, ModalState> {
73
+ static defaultProps: Partial<ModalProps> = {
74
+ onBackdropPress: () => null,
75
+ onHide: () => null,
76
+ visible: false,
77
+ useNativeDriver: false,
78
+ };
79
+
80
+ state: ModalState = {
81
+ visible: Boolean(this.props.visible),
82
+ currentAnimation: "none",
83
+ };
84
+
85
+ animVal = new Animated.Value(0);
86
+ _isMounted = false;
87
+
88
+ componentDidMount() {
89
+ this._isMounted = true;
90
+ if (this.state.visible) {
91
+ this.show();
92
+ }
93
+ }
94
+
95
+ componentWillUnmount() {
96
+ this._isMounted = false;
97
+ }
98
+
99
+ componentDidUpdate(prevProps: ModalProps) {
100
+ if (this.props.visible && !prevProps.visible) {
101
+ this.show();
102
+ } else if (!this.props.visible && prevProps.visible) {
103
+ this.hide();
104
+ }
105
+ }
106
+
107
+ show = () => {
108
+ this.setState({ visible: true, currentAnimation: "in" }, () => {
109
+ Animated.timing(this.animVal, {
110
+ easing: Easing.inOut(Easing.quad),
111
+ useNativeDriver: Boolean(this.props.useNativeDriver),
112
+ duration: MODAL_ANIM_DURATION,
113
+ toValue: 1,
114
+ }).start(() => {
115
+ this.setState({ currentAnimation: "none" });
116
+ });
117
+ });
118
+ };
119
+
120
+ hide = () => {
121
+ this.setState({ currentAnimation: "out" }, () => {
122
+ Animated.timing(this.animVal, {
123
+ easing: Easing.inOut(Easing.quad),
124
+ useNativeDriver: Boolean(this.props.useNativeDriver),
125
+ duration: MODAL_ANIM_DURATION,
126
+ toValue: 0,
127
+ }).start(() => {
128
+ if (this._isMounted) {
129
+ this.setState({ currentAnimation: "none" });
130
+ this.setState({ visible: false }, this.props.onHide);
131
+ }
132
+ });
133
+ });
134
+ };
135
+
136
+ render() {
137
+ const {
138
+ children,
139
+ onBackdropPress,
140
+ contentStyle,
141
+ ...otherProps
142
+ } = this.props;
143
+ const { currentAnimation, visible } = this.state;
144
+
145
+ const backdropAnimatedStyle = {
146
+ opacity: this.animVal.interpolate({
147
+ inputRange: [0, 1],
148
+ outputRange: [0, MODAL_BACKDROP_OPACITY],
149
+ }),
150
+ };
151
+
152
+ const contentAnimatedStyle =
153
+ currentAnimation === "in"
154
+ ? {
155
+ opacity: this.animVal.interpolate({
156
+ inputRange: CONTENT_ANIMATION_IN.opacity.inputRange,
157
+ outputRange: CONTENT_ANIMATION_IN.opacity.outputRange,
158
+ extrapolate: "clamp",
159
+ }),
160
+ transform: [
161
+ {
162
+ scale: this.animVal.interpolate({
163
+ inputRange: CONTENT_ANIMATION_IN.scale.inputRange,
164
+ outputRange: CONTENT_ANIMATION_IN.scale.outputRange,
165
+ extrapolate: "clamp",
166
+ }),
167
+ },
168
+ ],
169
+ }
170
+ : {
171
+ opacity: this.animVal.interpolate({
172
+ inputRange: CONTENT_ANIMATION_OUT.opacity.inputRange,
173
+ outputRange: CONTENT_ANIMATION_OUT.opacity.outputRange,
174
+ extrapolate: "clamp",
175
+ }),
176
+ };
177
+
178
+ return (
179
+ <ReactNativeModal
180
+ transparent
181
+ animationType="none"
182
+ {...otherProps}
183
+ visible={visible}
184
+ >
185
+ <TouchableWithoutFeedback onPress={onBackdropPress}>
186
+ <Animated.View style={[styles.backdrop, backdropAnimatedStyle]} />
187
+ </TouchableWithoutFeedback>
188
+ {visible && (
189
+ <Animated.View
190
+ style={[styles.content, contentAnimatedStyle, contentStyle]}
191
+ pointerEvents="box-none"
192
+ needsOffscreenAlphaCompositing={["in", "out"].includes(
193
+ currentAnimation
194
+ )}
195
+ >
196
+ {children}
197
+ </Animated.View>
198
+ )}
199
+ </ReactNativeModal>
200
+ );
201
+ }
202
+ }
203
+
204
+ const styles = StyleSheet.create({
205
+ backdrop: {
206
+ position: "absolute",
207
+ top: 0,
208
+ bottom: 0,
209
+ left: 0,
210
+ right: 0,
211
+ backgroundColor: "black",
212
+ opacity: 0,
213
+ },
214
+ content: {
215
+ flex: 1,
216
+ alignItems: "center",
217
+ justifyContent: "center",
218
+ },
219
+ });
220
+
221
+ export default Modal;
@@ -1,97 +1,97 @@
1
- import { StyleSheet } from "react-native";
1
+ import { Platform, PlatformColor, StyleSheet } from "react-native";
2
2
 
3
3
 
4
- interface styleInappProps {
5
- SLIDER_WIDTH: number;
6
- }
7
- export const styleInapp = ({ SLIDER_WIDTH }: styleInappProps) => StyleSheet.create({
8
- carouselContainer: {
9
- width: "100%",
10
- marginTop: 10,
11
- },
12
- styleContainer: {
13
- backgroundColor: 'white',
14
- elevation: 10,
15
- borderRadius: 10,
16
- width: SLIDER_WIDTH * 0.8,
17
- height: 480,
18
- },
19
- counter: {
20
- alignSelf: 'center',
21
- marginVertical: 10
22
- },
4
+ export const buildStyles = (data: any) => StyleSheet.create({
23
5
  closeButton: {
24
6
  position: 'absolute',
25
- alignSelf: 'flex-end',
26
- right: 20,
27
- top: 20,
28
- width: 30,
29
- height: 30,
30
- borderRadius: 20,
31
- backgroundColor: '#00000020',
32
- justifyContent: 'center',
33
- alignItems: 'center',
34
- zIndex: 90,
35
- },
36
- });
37
-
38
- interface styleItemProps {
39
- msg: any,
40
- checkBG: Function,
41
- }
42
- export const styleItem = ({ msg, checkBG }: styleItemProps) => StyleSheet.create({
43
- btn_left: {
44
- backgroundColor: msg.btn_left_bg_color || "#FFFFFF",
45
- height: 40,
46
- width: 100,
47
- alignItems: 'center',
48
- justifyContent: 'center',
49
- marginRight: 20,
50
- marginLeft: 10,
51
- flex: 1
52
- },
53
- btn_right: {
54
- backgroundColor: msg.btn_right_bg_color || "#FFFFFF",
55
- height: 40,
56
- width: 100,
57
- alignItems: 'center',
58
- justifyContent: 'center',
59
- marginRight: 10,
60
- flex: 1
7
+ top: 10,
8
+ right: 10,
9
+ zIndex: 10,
61
10
  },
62
- btn_left_title: {
63
- color: msg.btn_left_txt_color || "#000000"
11
+ content: Platform.select({
12
+ android: {
13
+ backgroundColor: data?.background_color,
14
+ flexDirection: "column",
15
+ borderRadius: 3,
16
+ padding: 16,
17
+ margin: 16,
18
+ overflow: "hidden",
19
+ elevation: 10,
20
+ minWidth: 300,
21
+ alignItems: "center"
22
+ },
23
+ default: {}
24
+ }),
25
+ messageData: Platform.select({
26
+ android: {
27
+ marginTop: 12
28
+ },
29
+ default: {}
30
+ }),
31
+ footer: {
32
+ flexDirection: "row",
33
+ ...Platform.select({
34
+ android: {
35
+ alignItems: "center",
36
+ justifyContent: "flex-end",
37
+ marginTop: 4,
38
+ },
39
+ default: {},
40
+ }),
64
41
  },
65
- btn_right_title: {
66
- color: msg.btn_right_txt_color || "#000000"
67
- },
68
- body: {
69
- backgroundColor: checkBG(),
70
- width: '100%',
71
- height: 450,
72
- alignSelf: 'center',
73
- alignItems: 'center',
74
- justifyContent: 'center',
75
- },
76
- bodyText: {
77
- color: msg.body_font_color || "#000000",
78
- textAlign: 'justify',
79
- marginBottom: 10,
80
- fontSize: 15,
81
- marginHorizontal: 10
82
- },
83
- title: {
84
- color: msg.title_font_color || "#000000",
85
- fontWeight: "bold",
86
- fontSize: 18,
87
- marginTop: 40
88
- },
89
- dot: {
90
- backgroundColor: msg.dot_color || "#FFFFFF",
91
- borderRadius: 100,
92
- width: 8,
93
- height: 8,
94
- marginLeft: 5,
95
- elevation: 5,
96
- }
97
- });
42
+ title: Platform.select({
43
+ android: {
44
+ color: PlatformColor(
45
+ `@android:color/${"primary_text_light"}`
46
+ ),
47
+ fontWeight: "500",
48
+ fontSize: 18,
49
+ },
50
+
51
+ default: {},
52
+ }),
53
+ body: Platform.select({
54
+ android: {
55
+ color: PlatformColor(
56
+ `@android:color/${"secondary_text_light"}`
57
+ ),
58
+ fontSize: 16,
59
+ marginTop: 10,
60
+ marginBottom: 10,
61
+ },
62
+ default: {},
63
+ }),
64
+ buttonLeft: Platform.select({
65
+ android: {
66
+ margin: 2,
67
+ flex: 1,
68
+ backgroundColor: data?.btn_left_bg_color,
69
+ justifyContent: "center",
70
+ alignItems: "center",
71
+ },
72
+ default: {},
73
+ }),
74
+ buttonRight: Platform.select({
75
+ android: {
76
+ margin: 2,
77
+ flex: 1,
78
+ backgroundColor: data?.btn_right_bg_color,
79
+ justifyContent: "center",
80
+ alignItems: "center",
81
+ },
82
+ default: {},
83
+ }),
84
+ textButton: Platform.select({
85
+ android: {
86
+ color: PlatformColor(
87
+ `@android:color/${"secondary_text_light"}`
88
+ ),
89
+ textAlign: "center",
90
+ backgroundColor: "transparent",
91
+ padding: 8,
92
+ fontSize: 14,
93
+ textTransform: "uppercase",
94
+ },
95
+ default: {},
96
+ }),
97
+ })
@@ -0,0 +1,117 @@
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
+ const notificationData = remoteMessage.data;
38
+
39
+ if (InngageProperties.getDebugMode())
40
+ console.log('Remote message received in foreground: ', remoteMessage);
41
+
42
+ if (firebaseListenCallback != null && remoteMessage != null)
43
+ firebaseListenCallback(notificationData)
44
+
45
+ PushNotification.localNotification({
46
+ autoCancel: true,
47
+ bigPictureUrl: remoteMessage.notification?.android?.imageUrl,
48
+ largeIconUrl: remoteMessage.notification?.android?.imageUrl,
49
+ title: notificationData?.title,
50
+ message: notificationData?.body,
51
+ vibration: 300,
52
+ channelId: "channel_id",
53
+ });
54
+
55
+ if (notificationData.additional_data != null)
56
+ await AsyncStorage.setItem('inapp', notificationData.additional_data);
57
+
58
+ };
59
+
60
+ return messaging().onMessage(handleMessage);
61
+ }, []);
62
+
63
+ useEffect(() => {
64
+ const backgroundHandler = async (remoteMessage: any) => {
65
+ const notificationData = remoteMessage.data;
66
+
67
+ if (InngageProperties.getDebugMode())
68
+ console.log('Remote message received in background: ', remoteMessage);
69
+
70
+ if (remoteMessage != null)
71
+ firebaseListenCallback(remoteMessage.data)
72
+
73
+ if (notificationData.additional_data != null)
74
+ await AsyncStorage.setItem('inapp', notificationData.additional_data);
75
+
76
+ messaging().onNotificationOpenedApp(remoteMessage => {
77
+ handleNotification(remoteMessage)
78
+ })
79
+ };
80
+
81
+ return messaging().setBackgroundMessageHandler(backgroundHandler);
82
+ }, []);
83
+
84
+ useEffect(() => {
85
+ messaging().getInitialNotification().then(async (value) => {
86
+
87
+ if (value !== null)
88
+ handleUniqueRemoteMessage(value);
89
+ });
90
+ }, [])
91
+
92
+ const handleUniqueRemoteMessage = async (
93
+ remoteMessage: { messageId?: string }) => {
94
+ try {
95
+ const lastRemoteMessageId = await AsyncStorage.getItem('LAST_REMOTE_MESSAGE_ID');
96
+ const newRemoteMessageId = remoteMessage?.messageId;
97
+
98
+ if (newRemoteMessageId && lastRemoteMessageId !== newRemoteMessageId) {
99
+ await AsyncStorage.setItem('LAST_REMOTE_MESSAGE_ID', newRemoteMessageId);
100
+ handleNotification(remoteMessage)
101
+ }
102
+ } catch (e) {
103
+ console.log(e);
104
+ }
105
+ };
106
+
107
+ async function handleNotification(remoteMessage) {
108
+ const notId = remoteMessage.data?.notId;
109
+ const request = {
110
+ notificationRequest: {
111
+ id: notId,
112
+ app_token: InngageProperties.appToken,
113
+ }
114
+ };
115
+ await ApiService.sendNotification(request);
116
+ }
117
+ }
package/src/index.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { Inapp } from './components/Inapp';
1
+ import { InAppContainer } from './components/in_app';
2
2
  import Inngage from './Inngage';
3
3
 
4
4
  //-------------- In-APP Component -------------//
5
- export { Inapp };
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/utils.ts CHANGED
@@ -24,30 +24,6 @@ export const showAlertLink = (title: string, body: string, appName: string, link
24
24
  })
25
25
  }
26
26
 
27
- export const subscriptionRequestAdapter = (sdkRequest, useCustomData, customData) => {
28
- if (useCustomData) {
29
- return {
30
- registerSubscriberRequest: {
31
- ...sdkRequest.registerSubscriberRequest,
32
- custom_field: customData
33
- }
34
- }
35
- }
36
- return {
37
- registerSubscriberRequest: {
38
- ...sdkRequest.registerSubscriberRequest
39
- }
40
- };
41
- }
42
-
43
- export const eventRequest = (request) => {
44
- return { ...request }
45
- }
46
-
47
- export const addUserDataRequest = (request) => {
48
- return { ...request }
49
- }
50
-
51
27
  export const isEmpty = (obj: any) => {
52
28
  for (var prop in obj) {
53
29
  if (obj.hasOwnProperty(prop)) {